/*
 *   This file is part of Dianara
 *   Copyright 2012-2016  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)
{
    this->pController = pumpController;
    this->globalObj = 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);
    this->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->getAvatar());
    if (QFile::exists(avatarFile))
    {
        this->updateAvatarIcon(avatarFile);
    }
    else
    {
        this->setGenericAvatarIcon();

        qDebug() << "AvatarButton() Using placeholder, downloading real avatar now";

        pController->enqueueAvatarForDownload(person->getAvatar());
        connect(pController, SIGNAL(avatarStored(QString,QString)),
                this, SLOT(redrawAvatar(QString,QString)));
    }


    this->authorId = person->getId();
    this->authorName = person->getNameWithFallback();
    this->authorUrl = person->getUrl();
    this->authorAvatarUrl = person->getAvatar();
    this->authorOutbox = person->getOutboxLink();

    this->authorFollowed = false; // Real status will be read when creating the menu


    createAvatarMenu();
    if (!authorId.isEmpty())  // Don't add the menu for invalid users
    {
        this->setMenu(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(this->iconWidth,
                                 Qt::SmoothTransformation));
}


void AvatarButton::updateAvatarIcon(QString filename)
{
    QPixmap avatarPixmap = QPixmap(filename)
                           .scaledToWidth(this->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()
{
    bool userIsAuthor = false;
    if (authorId == pController->currentUserId())
    {
        userIsAuthor = true; // The post or comment is ours
    }

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

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


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


    this->avatarMenuFollowAction = new QAction("*follow/unfollow*", this);
    // Connections and proper label are set in setFollowUnfollow()

    this->avatarMenuMessageAction = new QAction(QIcon::fromTheme("document-edit",
                                                                 QIcon(":/images/button-edit.png")),
                                                tr("Send message to %1")
                                                .arg(this->authorName),
                                                this);
    connect(avatarMenuMessageAction, SIGNAL(triggered()),
            this, SLOT(sendMessageToUser()));


    this->avatarMenuBrowseAction = new QAction(QIcon::fromTheme("edit-find",
                                                                QIcon(":/images/menu-find.png")),
                                               tr("Browse messages"),
                                               this);
    connect(avatarMenuBrowseAction, SIGNAL(triggered()),
            this, SLOT(browseUserMessages()));

    // Disable 'browse' option if not available (empty or in another server)
    if (!pController->urlIsInOurHost(this->authorOutbox))
    {
        this->avatarMenuBrowseAction->setDisabled(true);
    }


    // Only add "follow/unfollow", "send message" and "browse messages"
    if (!userIsAuthor)  // options if we're not the author
    {
        avatarMenu->addAction(avatarMenuFollowAction);
        this->syncFollowState(true);
        avatarMenu->addAction(avatarMenuMessageAction);
        avatarMenu->addAction(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 = this->authorFollowed;

    this->authorFollowed = this->pController->userInFollowing(authorId);

    if (this->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 (this->authorFollowed)
    {
        this->avatarMenuFollowAction->setIcon(QIcon::fromTheme("list-remove-user",
                                                               QIcon(":/images/list-remove.png")));
        this->avatarMenuFollowAction->setText(tr("Stop following"));
        connect(avatarMenuFollowAction, SIGNAL(triggered()),
                this, SLOT(unfollowUser()));
        disconnect(avatarMenuFollowAction, SIGNAL(triggered()),
                   this, SLOT(followUser()));
        //qDebug() << "post author followed, connecting to UNFOLLOW()" << this->authorId;
    }
    else
    {
        this->avatarMenuFollowAction->setIcon(QIcon::fromTheme("list-add-user",
                                                               QIcon(":/images/list-add.png")));
        this->avatarMenuFollowAction->setText(tr("Follow"));
        connect(avatarMenuFollowAction, SIGNAL(triggered()),
                this, SLOT(followUser()));
        disconnect(avatarMenuFollowAction, SIGNAL(triggered()),
                   this, SLOT(unfollowUser()));
        //qDebug() << "post author not followed, connecting to FOLLOW()" << this->authorId;
    }
}

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

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



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


void AvatarButton::openAuthorProfileInBrowser()
{
    QDesktopServices::openUrl(this->authorUrl);
}


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


void AvatarButton::unfollowUser()
{
    QString nameWithId = ASPerson::makeNameIdString(this->authorName,
                                                    this->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"), "", 1, 1);

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


void AvatarButton::sendMessageToUser()
{
    this->globalObj->createMessageForContact(this->authorId,
                                             this->authorName,
                                             this->authorUrl);

}

void AvatarButton::browseUserMessages()
{
    this->globalObj->browseUserMessages(this->authorId,
                                        this->authorName,
                                        this->icon(),
                                        this->authorOutbox + "/major"); // TMP!
}



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

        disconnect(pController, SIGNAL(avatarStored(QString,QString)),
                   this, SLOT(redrawAvatar(QString,QString)));
    }
}
