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

ContactCard::ContactCard(PumpController *pumpController,
                         GlobalObject *globalObject,
                         ASPerson *asPerson,
                         QWidget *parent)  :  QFrame(parent)
{
    m_pumpController = pumpController;
    m_globalObject = globalObject;

    this->setFrameStyle(QFrame::Box | QFrame::Raised);
    this->setSizePolicy(QSizePolicy::Minimum,
                        QSizePolicy::MinimumExpanding);


    // Left widget, user avatar
    m_avatarLabel = new QLabel(this);  // FIXME -- Use an AvatarButton?

    m_contactAvatarUrl = asPerson->getAvatarUrl();

    // Get local file name, which is stored in base64 hash form
    QString avatarFilename = MiscHelpers::getCachedAvatarFilename(m_contactAvatarUrl);

    // Load avatar if already cached
    const bool validAvatar = this->setAvatar(avatarFilename);
    if (!validAvatar && !m_contactAvatarUrl.isEmpty())
    {
        connect(m_pumpController, &PumpController::avatarStored,
                this, &ContactCard::redrawAvatar);

        // Download avatar for next time
        m_pumpController->enqueueAvatarForDownload(m_contactAvatarUrl);
    }


    // Center widget, user info
    QFont nameFont;
    nameFont.setBold(true);
    nameFont.setUnderline(true);

    m_contactName = asPerson->getName(); // WithFallback()? FIXME
    m_contactId = asPerson->getId();
    m_contactUrl = asPerson->getUrl();
    m_contactOutbox = asPerson->getOutboxLink();

    const bool cardIsOwn = (m_contactId == m_pumpController->currentUserId());

    QString userInfoString = QString("<b><u>%1</u></b><br>").arg(m_contactName);
    userInfoString.append(QString("%1<br>").arg(m_contactId));
    userInfoString.append(QStringLiteral("<small>")
                          + tr("Hometown")
                          + QString(": %1").arg(asPerson->getHometown())
                          + QStringLiteral("</small>"));
    QString userCreationDate = asPerson->getCreatedAt();
    if (!userCreationDate.isEmpty())
    {
        userInfoString.append(QStringLiteral("<br /><small>")
                              + tr("Joined: %1")
                                .arg(Timestamp::fuzzyTime(userCreationDate))
                              + QStringLiteral("</small>"));
    }
    else
    {
        userCreationDate = asPerson->getupdatedAt();
        userInfoString.append(QStringLiteral("<br /><small>")
                              + tr("Updated: %1")
                                .arg(Timestamp::fuzzyTime(userCreationDate))
                              + QStringLiteral("</small>"));
    }

    m_userInfoLabel = new QLabel(this);
    m_userInfoLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
    m_userInfoLabel->setText(userInfoString);
    m_userInfoLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    m_userInfoLabel->setWordWrap(true);
    m_userInfoLabel->setSizePolicy(QSizePolicy::Ignored,
                                   QSizePolicy::MinimumExpanding);


    // Bio as tooltip for the whole contact card
    QString contactBio = asPerson->getBio().replace("\n",
                                                    QStringLiteral("<br />"));
    if (!contactBio.isEmpty())
    {
        this->setToolTip("<b><u>" // Make it rich text, so that it gets wordwrapped
                         + tr("Bio for %1",
                              "Abbreviation for Biography, "
                              "but you can use the full word; "
                              "%1=contact name")
                           .arg(m_contactName)
                         + "</u></b>"
                         "<br><br>"
                         + contactBio);
    }
    else
    {
        if (m_contactName.isEmpty())
        {
            this->setToolTip(QStringLiteral("<b></b>")
                             + tr("This user doesn't have a biography"));
        }
        else
        {
            this->setToolTip(QStringLiteral("<b></b>")
                             + tr("No biography for %1",
                                  "%1=contact name").arg(m_contactName));
        }
    }


    // Right column, buttons
    m_followButton = new QPushButton(this);
    m_followButton->setFlat(true);
    if (asPerson->isFollowed())
    {
        this->setButtonToUnfollow();
    }
    else
    {
        if (!cardIsOwn)
        {
            this->setButtonToFollow();
        }
        else // Ourselves!
        {
            m_followButton->setText(QString());
            m_followButton->setDisabled(true);
        }
    }


    m_openProfileAction = new QAction(QIcon::fromTheme("internet-web-browser",
                                                       QIcon(":/images/button-download.png")),
                                      tr("Open Profile in Web Browser"),
                                      this);
    connect(m_openProfileAction, &QAction::triggered,
            this, &ContactCard::openProfileInBrowser);
    if (m_contactUrl.isEmpty()) // Disable if there is no URL
    {
        m_openProfileAction->setDisabled(true);
    }

    m_sendMessageAction = new QAction(QIcon::fromTheme("document-edit",
                                                       QIcon(":/images/button-edit.png")),
                                      tr("Send Message"),
                                      this);
    m_sendMessageAction->setDisabled(cardIsOwn);
    connect(m_sendMessageAction, &QAction::triggered,
            this, &ContactCard::setMessagingModeForContact);

    m_browsePostsAction = new QAction(QIcon::fromTheme("edit-find",
                                                       QIcon(":/images/menu-find.png")),
                                      tr("Browse Messages"),
                                      this);
    connect(m_browsePostsAction, &QAction::triggered,
            this, &ContactCard::browseContactPosts);


/*
    m_addToListMenu = new QMenu(tr("In Lists..."), this);
    m_addToListMenu->setIcon(QIcon::fromTheme("format-list-unordered"));
    m_addToListMenu->addAction("fake list 1")->setCheckable(true); // FIXME...
    m_addToListMenu->addAction("fake list 2")->setCheckable(true);
    m_addToListMenu->addAction("fake list 3")->setCheckable(true);
*/

    m_optionsMenu = new QMenu(QStringLiteral("*user-options*"), this);
    m_optionsMenu->addAction(m_openProfileAction);
    m_optionsMenu->addAction(m_sendMessageAction);
    m_optionsMenu->addAction(m_browsePostsAction);
    m_browsePostsAction->setEnabled(m_pumpController->urlIsInOurHost(m_contactOutbox));
    //m_optionsMenu->addMenu(m_addToListMenu); // Don't include it for now -- FIXME


    m_optionsButton = new QPushButton(QIcon::fromTheme("user-properties",
                                                       QIcon(":/images/no-avatar.png")),
                                      tr("User Options"),
                                      this);
    m_optionsButton->setFlat(true);
    m_optionsButton->setMenu(m_optionsMenu);


    // Layout
    m_rightLayout = new QVBoxLayout();
    m_rightLayout->setAlignment(Qt::AlignTop);
    m_rightLayout->addWidget(m_followButton);
    m_rightLayout->addWidget(m_optionsButton);

    m_mainLayout = new QHBoxLayout();
    m_mainLayout->addWidget(m_avatarLabel,   0, Qt::AlignTop);
    m_mainLayout->addWidget(m_userInfoLabel, 1);
    m_mainLayout->addLayout(m_rightLayout);
    this->setLayout(m_mainLayout);

    qDebug() << "ContactCard created" << m_contactId;
}


ContactCard::~ContactCard()
{
    qDebug() << "ContactCard destroyed" << m_contactId;
}



void ContactCard::setButtonToFollow()
{
    m_followButton->setIcon(QIcon::fromTheme("list-add",
                                             QIcon(":/images/list-add.png")));
    m_followButton->setText(tr("Follow"));
    connect(m_followButton, &QAbstractButton::clicked,
            this, &ContactCard::followContact);
    disconnect(m_followButton, &QAbstractButton::clicked,
               this, &ContactCard::unfollowContact);
}


void ContactCard::setButtonToUnfollow()
{
    m_followButton->setIcon(QIcon::fromTheme("list-remove",
                                             QIcon(":/images/list-remove.png")));
    m_followButton->setText(tr("Stop Following"));
    connect(m_followButton, &QAbstractButton::clicked,
            this, &ContactCard::unfollowContact);
    disconnect(m_followButton, &QAbstractButton::clicked,
               this, &ContactCard::followContact);
}


bool ContactCard::setAvatar(QString avatarFilename)
{
    bool validAvatar = false;

    QPixmap avatarPixmap = QPixmap(avatarFilename)
                           .scaledToWidth(64, Qt::SmoothTransformation);
    if (!avatarPixmap.isNull())
    {
        m_avatarLabel->setPixmap(avatarPixmap);
        validAvatar = true;
    }


    if (!validAvatar)
    {
        // Placeholder image
        m_avatarLabel->setPixmap(QIcon::fromTheme("user-identity",
                                                  QIcon(":/images/no-avatar.png"))
                                       .pixmap(64, 64));
    }

    return validAvatar;
}


QString ContactCard::getNameAndIdString()
{
    return QString("%1 <%2>").arg(m_contactName, m_contactId);
}

QString ContactCard::getId()
{
    return m_contactId;
}



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



void ContactCard::followContact()
{
    m_pumpController->followContact(m_contactId);
    this->setButtonToUnfollow(); // FIXME: should wait for proper signal
}


void ContactCard::unfollowContact()
{
    const QString nameWithId = ASPerson::makeNameIdString(m_contactName,
                                                          m_contactId);

    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_contactId);
        this->setButtonToFollow();  // FIXME: should wait for proper signal -- TODO
    }
}


void ContactCard::openProfileInBrowser()
{
    MiscHelpers::openUrl(m_contactUrl, this);
}

void ContactCard::setMessagingModeForContact()
{
    m_globalObject->createMessageForContact(m_contactId,
                                            m_contactName,
                                            m_contactUrl);
}

void ContactCard::browseContactPosts()
{
    const QPixmap contactPixmap(m_avatarLabel->pixmap()->copy());

    m_globalObject->browseUserMessages(m_contactId,
                                       m_contactName,
                                       QIcon(contactPixmap),
                                       m_contactOutbox + "/major"); // TMP! FIXME
}



/*
 * Redraw contact's avatar after it's been downloaded and stored
 *
 */
void ContactCard::redrawAvatar(QString avatarUrl, QString avatarFilename)
{
    if (avatarUrl == m_contactAvatarUrl)
    {
        disconnect(m_pumpController, &PumpController::avatarStored,
                   this, &ContactCard::redrawAvatar);

        this->setAvatar(avatarFilename);
    }
}
