/*
 *   This file is part of Dianara
 *   Copyright 2012-2019  JanKusanagi JRR <jancoding@gmx.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "profileeditor.h"


ProfileEditor::ProfileEditor(PumpController *pumpController,
                             QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle(tr("Profile Editor") + " - Dianara");
    this->setWindowIcon(QIcon::fromTheme("user-properties",
                                         QIcon(":/images/no-avatar.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);
    this->setMinimumSize(500, 400);

    QSettings settings;
    this->resize(settings.value("ProfileEditor/profileWindowSize",
                                QSize(580, 480)).toSize());


    m_pumpController = pumpController;
    connect(m_pumpController, &PumpController::avatarStored,
            this, &ProfileEditor::redrawAvatar);


    QFont infoFont;
    infoFont.setPointSize(infoFont.pointSize() - 1);

    m_webfingerLabel = new QLabel(this);
    m_webfingerLabel->setFont(infoFont);
    m_webfingerLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
    m_webfingerLabel->setToolTip("<b></b>"
                                 + tr("This is your Pump address"));

    const QString emailExplanation = tr("This is the e-mail address associated "
                                        "with your account, for things such as "
                                        "notifications and password recovery");

    m_emailChanger = new EmailChanger(emailExplanation,
                                      m_pumpController,
                                      this);

    m_emailLabel = new QLabel(this);
    m_emailLabel->setTextFormat(Qt::PlainText);
    m_emailLabel->setFont(infoFont);
    m_emailLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
    m_emailLabel->setToolTip("<b></b>" // Make the tooltip HTML so it gets wordwrap
                           + emailExplanation);

    m_changeEmailButton = new QPushButton(QIcon::fromTheme("view-pim-mail",
                                                           QIcon(":/images/button-post.png")),
                                          tr("Change &E-mail..."),
                                          this);
    connect(m_changeEmailButton, &QAbstractButton::clicked,
            m_emailChanger, &QWidget::show);


    m_avatarLabel = new QLabel(this);
    m_avatarLabel->setPixmap(QIcon::fromTheme("user-properties",
                                              QIcon(":/images/no-avatar.png"))
                             .pixmap(96, 96));

    m_changeAvatarButton = new QPushButton(QIcon::fromTheme("folder-image-people"),
                                           tr("Change &Avatar..."),
                                           this);
    connect(m_changeAvatarButton, &QAbstractButton::clicked,
            this, &ProfileEditor::findAvatarFile);

    m_avatarHasChanged = false;


    m_fullNameLineEdit = new QLineEdit(this);
    m_fullNameLineEdit->setToolTip("<b></b>"
                                   + tr("This is your visible name"));
    connect(m_fullNameLineEdit, &QLineEdit::textEdited,
            this, &ProfileEditor::enableSaveButton);

    m_hometownLineEdit = new QLineEdit(this);
    connect(m_hometownLineEdit, &QLineEdit::textEdited,
            this, &ProfileEditor::enableSaveButton);

    m_bioTextEdit = new QTextEdit(this);
    m_bioTextEdit->setTabChangesFocus(true);
    m_bioTextEdit->setSizePolicy(QSizePolicy::MinimumExpanding,
                                 QSizePolicy::MinimumExpanding);
    connect(m_bioTextEdit, &QTextEdit::textChanged,
            this, &ProfileEditor::enableSaveButton);


    m_newAvatarInfoLabel = new QLabel("\n"
                                      + tr("Changing your avatar will create a "
                                           "post in your timeline with it.\n"
                                           "If you delete that post your avatar "
                                           "will be deleted too.")
                                      + "\n",
                                      this);
    m_newAvatarInfoLabel->setWordWrap(true);
    m_newAvatarInfoLabel->setAlignment(Qt::AlignCenter);
    m_newAvatarInfoLabel->setFrameStyle(QFrame::Box | QFrame::Raised);
    m_newAvatarInfoLabel->setAutoFillBackground(true);
    m_newAvatarInfoLabel->setForegroundRole(QPalette::HighlightedText);
    m_newAvatarInfoLabel->setBackgroundRole(QPalette::Highlight);
    m_newAvatarInfoLabel->hide();


    m_saveButton = new QPushButton(QIcon::fromTheme("document-save",
                                                    QIcon(":/images/button-save.png")),
                                   tr("&Save Profile"),
                                   this);
    connect(m_saveButton, &QAbstractButton::clicked,
            this, &ProfileEditor::saveProfile);

    m_cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                      QIcon(":/images/button-cancel.png")),
                                     tr("&Cancel"),
                                     this);
    connect(m_cancelButton, &QAbstractButton::clicked,
            this, &QWidget::close);

    // Buttons managed via DBB to have proper order on each desktop environment
    m_buttonBox = new QDialogButtonBox(this);
    m_buttonBox->addButton(m_saveButton, QDialogButtonBox::AcceptRole);
    m_buttonBox->addButton(m_cancelButton, QDialogButtonBox::RejectRole);


    // ESC to cancel, too
    m_cancelAction = new QAction(this);
    m_cancelAction->setShortcut(QKeySequence(Qt::Key_Escape));
    connect(m_cancelAction, &QAction::triggered,
            this, &QWidget::close);
    this->addAction(m_cancelAction);


    // Layout
    m_emailLayout = new QHBoxLayout();
    m_emailLayout->addWidget(m_emailLabel);
    m_emailLayout->addStretch(1);
    m_emailLayout->addWidget(m_changeEmailButton);

    m_avatarLayout = new QHBoxLayout();
    m_avatarLayout->addWidget(m_avatarLabel);
    m_avatarLayout->addStretch(1);
    m_avatarLayout->addWidget(m_changeAvatarButton);


    m_topLayout = new QFormLayout();
    m_topLayout->setContentsMargins(0, 0, 0, 0);
    m_topLayout->addRow(tr("Webfinger ID"), m_webfingerLabel);
    m_topLayout->addRow(tr("E-mail"),       m_emailLayout);

    m_topLayout->addRow(tr("Avatar"),       m_avatarLayout);

    m_topLayout->addRow(tr("Full &Name"),   m_fullNameLineEdit);
    m_topLayout->addRow(tr("&Hometown"),    m_hometownLineEdit);
    m_topLayout->addRow(tr("&Bio"),         m_bioTextEdit);
    // FIXME: the FormLayout doesn't let the bioTextEdit row grow taller than its sizeHint()


    m_mainLayout = new QVBoxLayout();
    m_mainLayout->addLayout(m_topLayout, 9);
    m_mainLayout->addWidget(m_newAvatarInfoLabel);
    m_mainLayout->addWidget(m_buttonBox, 1);
    this->setLayout(m_mainLayout);


    // Disable some stuff until profile is received
    this->toggleWidgetsEnabled(false);
    m_saveButton->setEnabled(false);

    qDebug() << "ProfileEditor created";
}



ProfileEditor::~ProfileEditor()
{
    qDebug() << "ProfileEditor destroyed";
}



/*
 * Fill the fields from received info
 *
 */
void ProfileEditor::setProfileData(QString avatarUrl, QString fullName,
                                   QString hometown, QString bio,
                                   QString eMail)
{
    m_webfingerLabel->setText(m_pumpController->currentUserId());
    if (eMail.isEmpty())
    {
        m_emailLabel->setText("<" + tr("Not set",
                                       "In reference to the e-mail "
                                       "not being set for the account")
                              + ">");
    }
    else
    {
        m_emailLabel->setText(eMail);
        m_emailChanger->setCurrentEmail(eMail);
    }

    m_currentAvatarUrl = avatarUrl;
    QString avatarFilename = MiscHelpers::getCachedAvatarFilename(m_currentAvatarUrl);
    if (QFile::exists(avatarFilename))
    {
        m_oldAvatarFilename = avatarFilename; // In case we need to restore, to cancel
        this->setAvatar(avatarFilename);
    }
    // If the avatar has not been downloaded yet, it will come later with a SIGNAL()

    m_fullNameLineEdit->setText(fullName);
    m_hometownLineEdit->setText(hometown);
    m_bioTextEdit->setText(bio);

    // Enable all widgets, since the profile is valid now
    this->toggleWidgetsEnabled(true);
    m_saveButton->setDisabled(true); // But disable Save button until necessary
}



void ProfileEditor::setAvatar(QString filename)
{
    m_avatarLabel->setPixmap(QPixmap(filename)
                             .scaled(96, 96,
                                     Qt::KeepAspectRatio,
                                     Qt::SmoothTransformation));
}


/*
 * Enable or disable some widgets depending on whether the profile has been received
 *
 */
void ProfileEditor::toggleWidgetsEnabled(bool state)
{
    m_changeEmailButton->setEnabled(state);
    m_changeAvatarButton->setEnabled(state);

    m_fullNameLineEdit->setEnabled(state);
    m_hometownLineEdit->setEnabled(state);
    m_bioTextEdit->setEnabled(state);
}


/****************************************************************************/
/******************************** SLOTS *************************************/
/****************************************************************************/


void ProfileEditor::redrawAvatar(QString avatarUrl, QString avatarFilename)
{
    if (avatarUrl == m_currentAvatarUrl)
    {
        m_oldAvatarFilename = avatarFilename;
        this->setAvatar(avatarFilename);
    }
}


void ProfileEditor::findAvatarFile()
{
    m_newAvatarFilename = QFileDialog::getOpenFileName(this,
                                                       tr("Select avatar image"),
                                                       QDir::homePath(),
                                                       tr("Image files")
                                                       + " (*.png *.jpg *.jpe "
                                                         "*.jpeg *.gif);;"
                                                       + tr("All files")
                                                       + " (*)");

    if (!m_newAvatarFilename.isEmpty())
    {
        qDebug() << "Selected" << m_newAvatarFilename << "as new avatar for upload";

        // FIXME: in the future, check file size and image size and scale
        //        the pixmap to something sane before uploading         -- TODO
        QPixmap avatarPixmap = QPixmap(m_newAvatarFilename);

        m_newAvatarContentType = MiscHelpers::getFileMimeType(m_newAvatarFilename);
        if (!avatarPixmap.isNull() && !m_newAvatarContentType.isEmpty())
        {
            this->setAvatar(m_newAvatarFilename);
            m_avatarHasChanged = true;
            m_newAvatarInfoLabel->show();

            this->enableSaveButton(); // Enable, since something has been changed
        }
        else
        {
            QMessageBox::warning(this,
                                 tr("Invalid image"),
                                 tr("The selected image is not valid."));
            qDebug() << "Invalid avatar file selected";
        }
    }
}



void ProfileEditor::saveProfile()
{
    if (m_avatarHasChanged)
    {
        connect(m_pumpController, &PumpController::avatarUploaded,
                this, &ProfileEditor::sendProfileData);

        m_pumpController->uploadFile(m_newAvatarFilename,
                                     m_newAvatarContentType,
                                     PumpController::UploadAvatarRequest);
    }
    else
    {
        this->sendProfileData(); // Without a new image ID
    }
}



void ProfileEditor::sendProfileData(QString newImageUrl)
{
    if (m_avatarHasChanged)
    {
        disconnect(m_pumpController, &PumpController::avatarUploaded,
                   this, &ProfileEditor::sendProfileData);

        m_avatarHasChanged = false; // For next time the dialog is shown
        m_newAvatarInfoLabel->hide();
    }

    QString newFullName = m_fullNameLineEdit->text().trimmed();
    if (newFullName.isEmpty())
    {
        // To avoid having empty names, use the username part from the ID
        newFullName = m_pumpController->currentUsername();
    }

    m_pumpController->updateUserProfile(newImageUrl,
                                        newFullName,
                                        m_hometownLineEdit->text().trimmed(),
                                        m_bioTextEdit->toPlainText().trimmed());

    this->close();
}


/*
 * Enable the 'Save' button when something actually changes
 *
 */
void ProfileEditor::enableSaveButton()
{
    m_saveButton->setEnabled(true);
}


/****************************************************************************/
/****************************** PROTECTED ***********************************/
/****************************************************************************/


void ProfileEditor::closeEvent(QCloseEvent *event)
{
    m_saveButton->setDisabled(true); // Disabled for next time

    // If this is still true, it means avatar was changed but editor was cancelled
    if (m_avatarHasChanged)
    {
        m_avatarHasChanged = false;

        this->setAvatar(m_oldAvatarFilename);
        m_newAvatarInfoLabel->hide();
    }

    QSettings settings;
    if (settings.isWritable())
    {
        settings.setValue("ProfileEditor/profileWindowSize", this->size());
    }

    this->hide();
    event->ignore();
}
