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

DraftsManager::DraftsManager(GlobalObject *globalObject,
                             QWidget *parent) : QWidget(parent)
{
    m_globalObject = globalObject;

    this->setWindowTitle(tr("Draft Manager") + " - Dianara");
    this->setWindowIcon(QIcon::fromTheme("document-edit",
                                         QIcon(":/images/button-edit.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);
    this->setMinimumSize(500, 400);

    QSettings settings;
    QSize savedWindowsize = settings.value("DraftsManager/"
                                           "draftsWindowSize").toSize();
    if (savedWindowsize.isValid())
    {
        this->resize(savedWindowsize);
    }

    // Prepare submenus for the exported "Drafts" button
    m_loadMenu = new QMenu(tr("Load"), this);
    m_loadMenu->setIcon(QIcon::fromTheme("document-open",
                                         QIcon(":/images/button-open.png")));
    connect(m_loadMenu, &QMenu::triggered,
            this, &DraftsManager::onDraftSelectedFromMenu);


    m_saveAction = new QAction(QIcon::fromTheme("document-save",
                                                QIcon(":/images/button-save.png")),
                               tr("Save"),
                               this);
    m_saveAction->setShortcut(QKeySequence("Ctrl+S"));
    connect(m_saveAction, &QAction::triggered,
            this, &DraftsManager::saveDraftRequested);


    m_showManagerAction = new QAction(QIcon::fromTheme("file-manager",
                                                       QIcon(":/images/button-open.png")),
                                      tr("Manage drafts..."),
                                      this);
    connect(m_showManagerAction, &QAction::triggered,
            this, &QWidget::show);


    m_draftsMenu = new QMenu("*drafts-menu*", this);
    m_draftsMenu->addMenu(m_loadMenu);
    m_draftsMenu->addAction(m_saveAction);
    m_draftsMenu->addSeparator();
    m_draftsMenu->addAction(m_showManagerAction);



    // Widgets to manage drafts
    m_listWidget = new QListWidget(this);
    connect(m_listWidget, &QListWidget::currentRowChanged,
            this, &DraftsManager::onDraftSelectedFromList);


    m_previewLabel = new QLabel(this);
    m_previewLabel->setAlignment(Qt::AlignTop);

    m_deleteButton = new QPushButton(QIcon::fromTheme("edit-delete",
                                                      QIcon(":/images/button-delete.png")),
                                     tr("&Delete selected draft"),
                                     this);
    connect(m_deleteButton, &QAbstractButton::clicked,
            this, &DraftsManager::deleteSelectedDraft);

    m_closeButton = new QPushButton(QIcon::fromTheme("window-close",
                                                     QIcon(":/images/button-close.png")),
                                    tr("&Close"),
                                    this);
    connect(m_closeButton, &QAbstractButton::clicked,
            this, &QWidget::close);

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


    // Layouts
    m_buttonsLayout = new QHBoxLayout();
    m_buttonsLayout->addWidget(m_deleteButton);
    m_buttonsLayout->addStretch(1);
    m_buttonsLayout->addWidget(m_closeButton);

    m_mainLayout = new QVBoxLayout();
    m_mainLayout->addWidget(m_listWidget,   2);
    m_mainLayout->addWidget(m_previewLabel, 1);
    m_mainLayout->addStretch();
    m_mainLayout->addSpacing(4);
    m_mainLayout->addLayout(m_buttonsLayout);
    this->setLayout(m_mainLayout);


    loadDraftsFromFile();

    qDebug() << "DraftsManager created";
}


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


void DraftsManager::loadDraftsFromFile()
{
    DataFile *dataFile = new DataFile(m_globalObject->getDataDirectory()
                                      + "/drafts/drafts.json",
                                      this);

    QVariantList draftsList = dataFile->loadData();

    int itemCount = 0;
    foreach (QVariant draftVariant, draftsList)
    {
        QString draftId = draftVariant.toMap().value("id").toString();
        if (!draftId.isEmpty()) // Don't load broken JSON
        {
            QAction *newAction = new QAction(draftId, this);
            newAction->setData(draftVariant);
            m_loadMenu->addAction(newAction);

            m_listWidget->addItem(draftId);

            ++itemCount;
        }
    }

    // Don't let the user try to access an empty menu, or delete from an empty list
    m_loadMenu->setDisabled(itemCount == 0);
    m_deleteButton->setDisabled(itemCount == 0);

    // Make first item in manager's list actually *look* selected
    m_listWidget->setCurrentRow(0);

    qDebug() << "Loaded " << itemCount << "items";
}


void DraftsManager::saveDraftsToFile()
{
    DataFile *dataFile = new DataFile(m_globalObject->getDataDirectory()
                                      + "/drafts/drafts.json",
                                      this);

    QVariantList draftsList;
    foreach (QAction *draftAction, m_loadMenu->actions())
    {
        draftsList.append(draftAction->data().toMap());
    }

    dataFile->saveData(draftsList);
}


void DraftsManager::saveDraft(QString title, QString body,
                              QString type, QString attachment,
                              QVariantMap audience, int position)
{
    bool hadDraftId = true;
    if (m_currentDraftId.isEmpty())
    {
        m_currentDraftId = this->generateDraftId(title, body);
        hadDraftId = false;
    }

    QVariantMap draftMap;
    draftMap.insert("id",          m_currentDraftId);
    draftMap.insert("title",       title);
    draftMap.insert("body",        body);
    draftMap.insert("type",        type);
    draftMap.insert("attachment",  attachment);
    draftMap.insert("audience",    audience);
    draftMap.insert("position",    position);

    if (hadDraftId)
    {
        foreach (QAction *action, m_loadMenu->actions())
        {
            if (action->text() == m_currentDraftId)
            {
                action->setData(draftMap);
                qDebug() << "Replaced draft:" << m_currentDraftId;
            }
        }
    }
    else
    {
        QAction *newAction = new QAction(m_currentDraftId, this);
        newAction->setData(draftMap);
        m_loadMenu->addAction(newAction);
        m_loadMenu->setEnabled(true);
        m_deleteButton->setEnabled(true);

        m_listWidget->addItem(newAction->text());
        qDebug() << "Created new draft with ID:" << m_currentDraftId;
    }

    saveDraftsToFile(); // TMP / FIXME
}

/*
 * Generate a draft ID based on possible title, body and current date+time
 *
 */
QString DraftsManager::generateDraftId(QString title, QString body)
{
    QString newId;
    if (title.isEmpty())
    {
        newId = "_untitled_-";
    }
    else
    {
        newId = title.left(16).trimmed() + "-";
    }

    QString bodySnippet = MiscHelpers::htmlToPlainText(body).left(10).trimmed();
    if (!bodySnippet.isEmpty())
    {
        newId.append(bodySnippet + "-");
    }

    newId = newId.toLower();
    newId.replace(QRegExp("\\s+"), "_");


    newId.append(QDate::currentDate().toString(Qt::ISODate)
                 + "-"
                 + QTime::currentTime().toString(Qt::ISODate));

    return newId;
}


void DraftsManager::updateDraftId(QString id)
{
    m_currentDraftId = id;
}



QMenu *DraftsManager::getDraftMenu()
{
    return m_draftsMenu;
}


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


void DraftsManager::onDraftSelectedFromMenu(QAction *selectedAction)
{
    QVariantMap draftMap = selectedAction->data().toMap();
    qDebug() << "Selected draft from menu:" << draftMap.value("id").toString();

    emit draftSelected(draftMap.value("id").toString(),
                       draftMap.value("title").toString(),
                       draftMap.value("body").toString(),
                       draftMap.value("type").toString(),
                       draftMap.value("attachment").toString(),
                       draftMap.value("audience").toMap(),
                       draftMap.value("position").toInt());
    // currentDraftId will be updated from Publisher, if draft is allowed to load
}


void DraftsManager::onDraftSelectedFromList(int row)
{
    if (row == -1) // For instance, after deleting the last draft
    {
        return;    // Avoid crashing
    }

    QVariantMap draftMap = m_loadMenu->actions().at(row)->data().toMap();

    QString title = draftMap.value("title").toString().trimmed();
    if (title.isEmpty())
    {
        title = "*" + tr("Untitled draft") + "*";
    }

    QString body = MiscHelpers::htmlToPlainText(draftMap.value("body").toString(),
                                                50);

    m_previewLabel->setText("<h2>" + title + "</h2>"
                            + body);
}


void DraftsManager::deleteSelectedDraft()
{
    int selectedDraft = m_listWidget->currentRow();

    if (selectedDraft != -1)
    {
        int confirm = QMessageBox::question(this, tr("Delete draft?"),
                                            tr("Are you sure you want to "
                                               "delete this draft?"),
                                            tr("&Yes, delete it"), tr("&No"),
                                            QString(), 1, 1);
        if (confirm != 0)
        {
            return;
        }

        QListWidgetItem *removedItem = m_listWidget->takeItem(selectedDraft);
        delete removedItem;

        // m_loadMenu's actions should be in sync, but don't delete blindly
        if (m_loadMenu->actions().count() > selectedDraft) // For last item, 1 > 0
        {
            QAction *selectedAction = m_loadMenu->actions().at(selectedDraft);
            QVariantMap draftMap = selectedAction->data().toMap();

            // If we're removing the draft currently being edited, detach from it...
            if (draftMap.value("id").toString() == m_currentDraftId)
            {
                m_currentDraftId.clear(); // by clearing draft ID
            }

            delete selectedAction;
        }

        if (m_listWidget->count() == 0)
        {
            m_deleteButton->setDisabled(true);
            m_previewLabel->clear();

            m_loadMenu->setDisabled(true);
        }
    }

    saveDraftsToFile(); // TMP FIXME, should be scheduled
}


//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// PROTECTED ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


void DraftsManager::showEvent(QShowEvent *event)
{
    emit windowShown();

    if (m_listWidget->currentRow() == -1)
    {
        // Ensure something's selected
        m_listWidget->setCurrentRow(0);
    }

    event->accept();
}


void DraftsManager::hideEvent(QHideEvent *event)
{
    QSettings settings;
    if (settings.isWritable())
    {
        settings.setValue("DraftsManager/draftsWindowSize", this->size());
    }

    event->accept();
}
