/*
 *   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 "avatarbutton.h"


AvatarButton::AvatarButton(ASPerson *person,
                           PumpController *pumpController,
                           GlobalObject *globalObject,
                           QSize avatarSize,
                           QWidget *parent) : QToolButton(parent)
{
    m_pumpController = pumpController;
    m_globalObject = globalObject;

    this->setPopupMode(QToolButton::InstantPopup);
    this->setStyleSheet("QToolButton { border: none;       "
                        "              border-radius: 8px; "
                        "              padding: 2px       }"
                        "QToolButton:hover { border: none;          "
                        "                    background-color:      "
                        "                       palette(highlight) }");
    this->setIconSize(avatarSize);
    this->setMinimumSize(avatarSize);
    m_iconWidth = avatarSize.width();

    this->setToolTip(person->getTooltipInfo());

    // Get local file name for avatar, which is stored in base64 hash form
    QString avatarFile = MiscHelpers::getCachedAvatarFilename(person->getAvatarUrl());
    if (QFile::exists(avatarFile))
    {
        this->updateAvatarIcon(avatarFile);
    }
    else
    {
        this->setGenericAvatarIcon();

        m_pumpController->enqueueAvatarForDownload(person->getAvatarUrl());
        connect(m_pumpController, &PumpController::avatarStored,
                this, &AvatarButton::redrawAvatar);
    }


    m_authorId = person->getId();
    m_authorName = person->getNameWithFallback();
    m_authorUrl = person->getUrl();
    m_authorAvatarUrl = person->getAvatarUrl();
    m_authorOutbox = person->getOutboxLink();

    m_authorFollowed = false; // Real status will be read when creating the menu


    createAvatarMenu();
    if (!m_authorId.isEmpty())  // Don't add the menu for invalid users
    {
        this->setMenu(m_avatarMenu);
    }


    qDebug() << "AvatarButton created";
}


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




void AvatarButton::setGenericAvatarIcon()
{
    this->setIcon(QIcon::fromTheme("user-identity",
                                   QIcon(":/images/no-avatar.png"))
                  .pixmap(this->iconSize())
                  .scaledToWidth(m_iconWidth, Qt::SmoothTransformation));
}


void AvatarButton::updateAvatarIcon(QString filename)
{
    const QPixmap avatarPixmap = QPixmap(filename)
                                 .scaledToWidth(m_iconWidth,
                                                Qt::SmoothTransformation);

    if (!avatarPixmap.isNull())
    {
        this->setIcon(QIcon(avatarPixmap));
    }
    else
    {
        qDebug() << "AvatarButton() avatar pixmap is null, using generic";
        this->setGenericAvatarIcon();
    }
}


/*
 * Create the menu shown when clicking the avatar
 *
 */
void AvatarButton::createAvatarMenu()
{
    const bool userIsAuthor = (m_authorId == m_pumpController->currentUserId());

    m_avatarMenu = new QMenu(this);
    m_avatarMenu->setSeparatorsCollapsible(false);

    m_avatarMenuIdAction = new QAction(QIcon::fromTheme("user-identity",
                                                        QIcon(":/images/no-avatar.png")),
                                       m_authorId,
                                       this);
    m_avatarMenuIdAction->setSeparator(true); // Make it nicer and not clickable
    m_avatarMenu->addAction(m_avatarMenuIdAction);


    QString openProfileString;
    if (userIsAuthor)
    {
        openProfileString = tr("Open your profile in web browser");
    }
    else
    {
        openProfileString = tr("Open %1's profile in web browser")
                            .arg(m_authorName);
    }
    m_avatarMenuProfileAction = new QAction(QIcon::fromTheme("internet-web-browser",
                                                             QIcon(":/images/no-avatar.png")),
                                            openProfileString,
                                            this);
    connect(m_avatarMenuProfileAction, &QAction::triggered,
            this, &AvatarButton::openAuthorProfileInBrowser);
    if (m_authorUrl.isEmpty()) // Disable if there isn't actually an URL
    {
        m_avatarMenuProfileAction->setDisabled(true);
    }
    m_avatarMenu->addAction(m_avatarMenuProfileAction);


    m_avatarMenuFollowAction = new QAction(this);
    // Connections and label are set in setFollowUnfollow()


    m_avatarMenuMessageAction = new QAction(QIcon::fromTheme("document-edit",
                                                             QIcon(":/images/button-edit.png")),
                                            tr("Send message to %1")
                                            .arg(m_authorName),
                                            this);
    connect(m_avatarMenuMessageAction, &QAction::triggered,
            this, &AvatarButton::sendMessageToUser);


    m_avatarMenuBrowseAction = new QAction(QIcon::fromTheme("edit-find",
                                                            QIcon(":/images/menu-find.png")),
                                           tr("Browse messages"),
                                           this);
    connect(m_avatarMenuBrowseAction, &QAction::triggered,
            this, &AvatarButton::browseUserMessages);

    // Disable 'browse' option if not available (empty or in another server; Pump issue)
    if (!m_pumpController->urlIsInOurHost(m_authorOutbox))
    {
        m_avatarMenuBrowseAction->setDisabled(true);
    }


    // Only add "follow/unfollow", "send message" and "browse messages"
    if (!userIsAuthor)  // options if we're not the author
    {
        m_avatarMenu->addAction(m_avatarMenuFollowAction);
        this->syncFollowState(true);
        m_avatarMenu->addAction(m_avatarMenuMessageAction);
        m_avatarMenu->addAction(m_avatarMenuBrowseAction);
    }

    //
    // More options can be added from outside, via addActionToMenu()
    //
}


/*
 * See if we're currently following this user, according to the contact list
 *
 */
void AvatarButton::syncFollowState(bool firstTime)
{
    bool authorFollowedBefore = m_authorFollowed;

    m_authorFollowed = m_pumpController->userInFollowing(m_authorId);

    if (m_authorFollowed != authorFollowedBefore || firstTime)
    {
        this->setFollowUnfollow();
    }
}



/*
 * Set the icon and text of the follow/unfollow option of the avatar menu
 * according to whether we're following that user or not
 *
 */
void AvatarButton::setFollowUnfollow()
{
    if (m_authorFollowed)
    {
        m_avatarMenuFollowAction->setIcon(QIcon::fromTheme("list-remove-user",
                                                           QIcon(":/images/list-remove.png")));
        m_avatarMenuFollowAction->setText(tr("Stop following"));
        connect(m_avatarMenuFollowAction, &QAction::triggered,
                this, &AvatarButton::unfollowUser);
        disconnect(m_avatarMenuFollowAction, &QAction::triggered,
                   this, &AvatarButton::followUser);
        //qDebug() << "post author followed, connecting to UNFOLLOW()" << this->authorId;
    }
    else
    {
        m_avatarMenuFollowAction->setIcon(QIcon::fromTheme("list-add-user",
                                                           QIcon(":/images/list-add.png")));
        m_avatarMenuFollowAction->setText(tr("Follow"));
        connect(m_avatarMenuFollowAction, &QAction::triggered,
                this, &AvatarButton::followUser);
        disconnect(m_avatarMenuFollowAction, &QAction::triggered,
                   this, &AvatarButton::unfollowUser);
        //qDebug() << "post author not followed, connecting to FOLLOW()" << this->authorId;
    }
}


void AvatarButton::addSeparatorToMenu()
{
    m_avatarMenu->addSeparator();
}


void AvatarButton::addActionToMenu(QAction *action)
{
    m_avatarMenu->addAction(action);
}


////////////////////////////////////////////////////////////////////////////
////////////////////////////////// SLOTS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////



void AvatarButton::openAuthorProfileInBrowser()
{
    MiscHelpers::openUrl(m_authorUrl, this);
}


void AvatarButton::followUser()
{
    m_pumpController->followContact(m_authorId);
    // Actual menu will be updated when appropriate SIGNAL is received
}


void AvatarButton::unfollowUser()
{
    const QString nameWithId = ASPerson::makeNameIdString(m_authorName,
                                                          m_authorId);

    int confirmation = QMessageBox::question(this, tr("Stop following?"),
                                             tr("Are you sure you want to "
                                                "stop following %1?")
                                             .arg(nameWithId),
                                             tr("&Yes, stop following"),
                                             tr("&No"), QString(), 1, 1);

    if (confirmation == 0)
    {
        m_pumpController->unfollowContact(m_authorId);
        // Menu option will be updated when appropriate SIGNAL is received
    }
}


void AvatarButton::sendMessageToUser()
{
    m_globalObject->createMessageForContact(m_authorId,
                                            m_authorName,
                                            m_authorUrl);
}

void AvatarButton::browseUserMessages()
{
    m_globalObject->browseUserMessages(m_authorId,
                                       m_authorName,
                                       this->icon(),
                                       m_authorOutbox + "/major"); // TMP! not future-proof
}



/*
 * Redraw avatar after receiving it
 *
 */
void AvatarButton::redrawAvatar(QString avatarUrl, QString avatarFilename)
{
    if (avatarUrl == m_authorAvatarUrl)
    {
        this->updateAvatarIcon(avatarFilename);

        disconnect(m_pumpController, &PumpController::avatarStored,
                   this, &AvatarButton::redrawAvatar);
    }
}
