#include "shopform.h"
#include "ui_shopform.h"
#include "directsaleform.h"
#include "temporaryreceiptsaveform.h"
#include "receiptsaveform.h"
#include "receiptloadform.h"
#include "shopservice.h"
#include "receiptgenerator.h"
#include "paydialog.h"
#include "paydvouchersdialog.h"
#include "isellableservice.h"
#include <QList>
#include <QSharedPointer>
#include <QSortFilterProxyModel>
#include <QMessageBox>

#include "shop-odb.hxx"

ShopForm::ShopForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ShopForm)
{
    ui->setupUi(this);
    m_itemsModel = NULL;
    m_commodityModel = NULL;

    ui->temporarySaveButton->setEnabled(false);
    ui->saveButton->setEnabled(false);
    ui->payButton->setEnabled(false);
}

ShopForm::~ShopForm()
{
    delete ui;
}

void ShopForm::loadLast()
{
    if (m_itemsModel == NULL)
    {
        m_itemsModel = new AutoTableModel<VoucherItem>(this);
        m_itemsModel->setEditableCols(QList<int>() << 1);
        m_itemsModel->setTranslations(Context::instance().plugin("SHOP")->translations());
        ui->actualReceipt->setModel(m_itemsModel);
        ui->actualReceipt->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
    }

    ShopService srv;
    QList<QSharedPointer<Voucher> > receipt = srv.all(QString("status = %1").arg(QString::number(Voucher::NEW)));
    if (!receipt.isEmpty())
    {
        m_voucher = receipt[0];
        srv.loadItems(m_voucher);
        m_itemsModel->setData(m_voucher->items());
        connectItemSignals();

        ui->total->setText(QString::number(m_voucher->totalPrice().toDouble(), 'f', 2));

        if (!m_voucher->items().isEmpty())
        {
            ui->temporarySaveButton->setEnabled(true);
            ui->saveButton->setEnabled(true);
            ui->payButton->setEnabled(true);
        }
    }

    if (m_commodityModel == NULL)
    {
        m_commodityModel = new AutoTableModel<ShopItem>(this);
        m_commodityModel->setTranslations(Context::instance().plugin("SHOP")->translations());
        ui->commodityTable->setModel(m_commodityModel);

        connect(ui->commodityTable->selectionModel(), &QItemSelectionModel::currentRowChanged, [this](const QModelIndex &current, const QModelIndex &){
            ui->btnAddItem->setEnabled(current.isValid());
        });
    }

    m_commodityModel->setData(srv.allSellableItems());
    ui->commodityTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui->commodityTable->setColumnHidden(3, true);

    if (srv.isEetEnabled())
    {
        ui->lblEetState->setText(srv.isEetOnline() ? tr("<a href=\"#eet\">Online</a>") : tr("<a href=\"#eet\">Offline</a>"));
    }
    else
    {
        ui->labelEete->setVisible(false);
        ui->lblEetState->setVisible(false);
    }
}

void ShopForm::fillRaceiptCombo()
{
    bool oldState = ui->receiptCombo->blockSignals(true);

    ShopService srv;
    QList<QSharedPointer<Voucher> > receipts = srv.all(QString("status = %1").arg(QString::number(Voucher::TEMPORARY)));

    ui->receiptCombo->clear();
    ui->receiptCombo->addItem(tr("<< empty >>"));

    foreach (QSharedPointer<Voucher> voucher, receipts) {
        ui->receiptCombo->addItem(voucher->name(), voucher->id());
    }

    ui->receiptCombo->blockSignals(oldState);
}

void ShopForm::on_directSale_clicked()
{
    if (m_voucher.isNull())
    {
        createVoucher();
    }

    DirectSaleForm *form = new DirectSaleForm(this);
    form->setAttribute(Qt::WA_DeleteOnClose);

    connect(form, &QDialog::accepted, [this, form](){
        addItem(form->shopItem(), ((DirectSaleItem*)form->shopItem().data())->count());
    });

    form->show();
}

void ShopForm::on_temporarySaveButton_clicked()
{
    doTempSave(false);
}

void ShopForm::on_saveButton_clicked()
{
    ReceiptSaveForm *form = new ReceiptSaveForm(m_voucher, this);
    form->setAttribute(Qt::WA_DeleteOnClose);

    connect(form, &QDialog::accepted, [this, form]() {
        ShopService srv;

        if (form->saveAsNew())
        {
            m_voucher->setStatus(Voucher::NOT_PAID);
            srv.saveVoucher(m_voucher);
            createEmptyVoucher();
        }
        else
        {
            VoucherPtr selVoucher = form->selectedVoucher();
            srv.moveItems(m_voucher->items(), m_voucher, selVoucher);
            srv.calculate(selVoucher);
            srv.updateVoucher(selVoucher);
            createEmptyVoucher();
        }

        m_itemsModel->setData(m_voucher->items());
    });

    form->show();
}

void ShopForm::on_loadButton_clicked()
{
    ReceiptLoadForm *form = new ReceiptLoadForm(this);
    form->setAttribute(Qt::WA_DeleteOnClose);

    connect(form, &QDialog::accepted, [this, form](){
        ShopService srv;

        if (m_voucher.isNull())
        {
            m_voucher = srv.createVoucher();
        }

        srv.moveItems(form->selectedItems(), form->selectedVoucher(), this->m_voucher);

        m_itemsModel->setData(m_voucher->items());

        connectItemSignals();
        onCountChanged();
    });

    form->show();
}

void ShopForm::onCountChanged(int oldCount/* = 0*/)
{
    VoucherItem *item = qobject_cast<VoucherItem*>(sender());
    if (item != NULL && item->count() == 0)
    {
        for (int i = 0; i < m_voucher->items().count(); i++)
        {
            if (m_voucher->items()[i].data() == item)
            {
                m_voucher->removeItem(m_voucher->items()[i]);
                m_itemsModel->setData(m_voucher->items());
            }
        }
    }

    ShopService srv;
    srv.calculate(m_voucher);
    ui->total->setText(QString::number(m_voucher->totalPrice().toDouble(), 'f', 2));
    ui->temporarySaveButton->setEnabled(!m_voucher->items().isEmpty());
    ui->saveButton->setEnabled(!m_voucher->items().isEmpty());
    ui->payButton->setEnabled(!m_voucher->items().isEmpty());

    if (m_voucher->status() == Voucher::NEW && m_voucher->id() == 0)
    {
        srv.saveVoucher(m_voucher);
    }
    else
    {
        srv.updateVoucher(m_voucher);
    }

    if (item != NULL)
    {
        int countAdded = item->count() - oldCount;
        srv.updateRelatedItem(item, countAdded);
    }
}

void ShopForm::createVoucher()
{
    ShopService srv;
    m_voucher = srv.createVoucher();
}

void ShopForm::doTempSave(bool comboChanged)
{
    TemporaryReceiptSaveForm *form = new TemporaryReceiptSaveForm(m_voucher, this);
    form->setAttribute(Qt::WA_DeleteOnClose);

    connect(form, &QDialog::accepted, [this, form, comboChanged](){
        ShopService srv;

        if (!m_voucher->items().isEmpty())
        {
            m_voucher->setStatus(Voucher::TEMPORARY);
            srv.updateVoucher(m_voucher);
        }

        if (comboChanged && ui->receiptCombo->currentIndex() > 0)
        {
            changeReceipt();
        }
        else
        {
            createEmptyVoucher();
        }

        fillRaceiptCombo();

        m_itemsModel->setData(m_voucher->items());
    });

    form->show();
}

void ShopForm::changeReceipt()
{
    ShopService srv;

    m_voucher = srv.loadById(ui->receiptCombo->currentData().toInt());
    srv.loadItems(m_voucher);
    connectItemSignals();
    m_voucher->setStatus(Voucher::NEW);
    srv.updateVoucher(m_voucher);

    m_itemsModel->setData(m_voucher->items());
    ui->total->setText(m_voucher->totalPrice().toString());

    ui->temporarySaveButton->setEnabled(true);
    ui->saveButton->setEnabled(true);
    ui->payButton->setEnabled(true);

    fillRaceiptCombo();
}

void ShopForm::connectItemSignals()
{
    foreach (QSharedPointer<VoucherItem> item, m_voucher->items()) {
        connect(item.data(), SIGNAL(countChanged(int)), this, SLOT(onCountChanged(int)));
    }
}

void ShopForm::createEmptyVoucher()
{
    ShopService srv;
    m_voucher = srv.createVoucher();
    ui->total->setText("0");
    ui->temporarySaveButton->setEnabled(false);
    ui->saveButton->setEnabled(false);
    ui->payButton->setEnabled(false);
}

void ShopForm::addItem(QSharedPointer<IShopItem> item, int count)
{
    ShopService srv;
    srv.addShopItem(m_voucher, item, count);
    this->m_itemsModel->addRow(m_voucher->items()[m_voucher->items().count() - 1]);
    connect(m_voucher->items()[m_voucher->items().count() - 1].data(), SIGNAL(countChanged(int)), this, SLOT(onCountChanged(int)));
    onCountChanged();
}

void ShopForm::on_receiptCombo_currentIndexChanged(int)
{
    if (!m_voucher.isNull() && m_voucher->items().isEmpty())
    {
        ShopService srv;
        srv.erase(m_voucher);
        changeReceipt();

        return;
    }

    if (m_voucher.isNull())
    {
        changeReceipt();
    }
    else
    {
        doTempSave(true);
    }
}

void ShopForm::on_payButton_clicked()
{
    PayDialog *dialog = new PayDialog(m_voucher->totalPrice(), this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->show();

    connect(dialog, &QDialog::accepted, [this, dialog](){
        ShopService srv;
        srv.pay(m_voucher);
        QString eetMsg;

        if (srv.isEetEnabled() && dialog->sendToEet())
        {
            bool eetRet = srv.processEet(m_voucher, eetMsg);

            if (!eetRet)
            {
                QString errMsg = tr("EET communication error.\n");

                if (!eetMsg.isEmpty())
                {
                    errMsg += tr("Message from portal: ") + eetMsg + "\n";
                }

                errMsg += tr("Switch to offline?");

                if (srv.isEetOnline() && QMessageBox::question(this, tr("EET error"), errMsg) == QMessageBox::Yes)
                {
                    srv.setEetOnline(false);
                    ui->lblEetState->setText(srv.isEetOnline() ? tr("<a href=\"#eet\">Online</a>") : tr("<a href=\"#eet\">Offline</a>"));
                }
            }
        }

        ReceiptGenerator generator;
        generator.setVoucher(m_voucher);
        generator.print();

        createEmptyVoucher();
        m_itemsModel->setData(m_voucher->items());
    });


}

void ShopForm::on_showPaiedButton_clicked()
{
    PaydVouchersDialog *dialog = new PaydVouchersDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->show();
}

void ShopForm::on_btnAddItem_clicked()
{
    if (m_voucher.isNull())
    {
        createVoucher();
    }

    ShopItemPtr item = m_commodityModel->itemFromIndex(ui->commodityTable->currentIndex());
    addItem(item, ui->spnCount->value());
}

void ShopForm::on_commoditySearch_textChanged(const QString &text)
{
    QSortFilterProxyModel proxy;
    proxy.setSourceModel(m_commodityModel);
    proxy.setFilterKeyColumn(0);
    proxy.setFilterCaseSensitivity(Qt::CaseInsensitive);
    proxy.setFilterFixedString(text);

    auto moveToIndex = [this](const QModelIndex &matchingIndex) {
        ui->commodityTable->scrollTo(matchingIndex,QAbstractItemView::EnsureVisible);
        ui->commodityTable->setCurrentIndex(matchingIndex);
    };

    QModelIndex matchingIndex = proxy.mapToSource(proxy.index(0,0));
    if(matchingIndex.isValid()) {
        moveToIndex(matchingIndex);
    }
    else
    {
        proxy.setFilterKeyColumn(1);
        matchingIndex = proxy.mapToSource(proxy.index(0,0));

        if (matchingIndex.isValid())
        {
            moveToIndex(matchingIndex);
        }
    }
}

void ShopForm::on_lblEetState_linkActivated(const QString &link)
{
    ShopService srv;
    srv.setEetOnline(!srv.isEetOnline());

    ui->lblEetState->setText(srv.isEetOnline() ? tr("<a href=\"#eet\">Online</a>") : tr("<a href=\"#eet\">Offline</a>"));
}
