#include "gui.h"

GUI::GUI(){
    this->repoSelector = new QWidget;
    this->mainMenu = new QWidget;
    this->adminMenu = new QWidget;
    this->userMenu = new QWidget;
    this->addMenu = new QWidget;
    this->deleteMenu = new QWidget;
    this->updateMenu = new QWidget;
    this->showMenu = new QWidget;

    this->repoSelectorLayout = new QVBoxLayout;
    this->mainMenuLayout = new QVBoxLayout;
    this->adminMenuLayout = new QVBoxLayout;
    this->userMenuLayout = new QVBoxLayout;
    this->addMenuLayout = new QFormLayout;
    this->deleteMenuLayout = new QFormLayout;
    this->updateMenuLayout = new QFormLayout;
    this->showMenuLayout = new QVBoxLayout;

    this->CSVBtn = new QPushButton("CSV");
    this->HTMLBtn = new QPushButton("HTML");

    this->adminBtn = new QPushButton("Admin");
    this->userBtn = new QPushButton("User");

    this->addBtn = new QPushButton("Add");
    this->deleteBtn = new QPushButton("Delete");
    this->updateBtn = new QPushButton("Update");
    this->showBtn = new QPushButton("Show");

    this->addingBtn = new QPushButton("Add");
    this->deletingBtn = new QPushButton("Delete");
    this->updatingBtn = new QPushButton("Update");

    this->adminExitBtn = new QPushButton("Exit");
    this->addExitBtn = new QPushButton("Exit");
    this->deleteExitBtn = new QPushButton("Exit");
    this->updateExitBtn = new QPushButton("Exit");
    this->showExitBtn = new QPushButton("Exit");

    this->addSize = new QLineEdit;
    this->addColour = new QLineEdit;
    this->addPrice = new QLineEdit;
    this->addQuantity = new QLineEdit;
    this->addPhotograph = new QLineEdit;

    this->deleteSize = new QLineEdit;
    this->deleteColour = new QLineEdit;
    this->deletePhotograph = new QLineEdit;

    this->updateSize = new QLineEdit;
    this->updateColour = new QLineEdit;
    this->updatePrice = new QLineEdit;
    this->updateQuantity = new QLineEdit;
    this->updatePhotograph = new QLineEdit;

    this->addSizeLabel = new QLabel("Size:");
    this->addColourLabel = new QLabel("Colour:");
    this->addPriceLabel = new QLabel("Price:");
    this->addQuantityLabel = new QLabel("Quantity:");
    this->addPhotographLabel = new QLabel("Photograph:");

    this->deleteSizeLabel = new QLabel("Size:");
    this->deleteColourLabel = new QLabel("Colour:");
    this->deletePhotographLabel = new QLabel("Photograph:");
    
    this->updateSizeLabel = new QLabel("Size:");
    this->updateColourLabel = new QLabel("Colour:");
    this->updatePriceLabel = new QLabel("Price: (leave empty to not update)");
    this->updateQuantityLabel = new QLabel("Quantity: (leave empty to not update)");
    this->updatePhotographLabel = new QLabel("Photograph:");

    this->addSizeLabel->setBuddy(this->addSize);
    this->addColourLabel->setBuddy(this->addColour);
    this->addPriceLabel->setBuddy(this->addPrice);
    this->addQuantityLabel->setBuddy(this->addQuantity);
    this->addPhotographLabel->setBuddy(this->addPhotograph);

    this->deleteSizeLabel->setBuddy(this->deleteSize);
    this->deleteColourLabel->setBuddy(this->deleteColour);
    this->deletePhotographLabel->setBuddy(this->deletePhotograph);

    this->updateSizeLabel->setBuddy(this->updateSize);
    this->updateColourLabel->setBuddy(this->updateColour);
    this->updatePriceLabel->setBuddy(this->updatePrice);
    this->updateQuantityLabel->setBuddy(this->updateQuantity);
    this->updatePhotographLabel->setBuddy(this->updatePhotograph);


    this->repoSelectorLayout->addWidget(this->CSVBtn);
    this->repoSelectorLayout->addWidget(this->HTMLBtn);
    this->repoSelector->setLayout(this->repoSelectorLayout);

    this->mainMenuLayout->addWidget(this->adminBtn);
    this->mainMenuLayout->addWidget(this->userBtn);
    this->mainMenu->setLayout(this->mainMenuLayout);

    this->adminMenuLayout->addWidget(this->addBtn);
    this->adminMenuLayout->addWidget(this->deleteBtn);
    this->adminMenuLayout->addWidget(this->updateBtn);
    this->adminMenuLayout->addWidget(this->showBtn);
    this->adminMenuLayout->addWidget(this->adminExitBtn);
    this->adminMenu->setLayout(this->adminMenuLayout);

    this->addMenuLayout->addRow(this->addSizeLabel, this->addSize);
    this->addMenuLayout->addRow(this->addColourLabel, this->addColour);
    this->addMenuLayout->addRow(this->addPriceLabel, this->addPrice);
    this->addMenuLayout->addRow(this->addQuantityLabel, this->addQuantity);
    this->addMenuLayout->addRow(this->addPhotographLabel, this->addPhotograph);
    this->addMenuLayout->addWidget(this->addingBtn);
    this->addMenuLayout->addWidget(this->addExitBtn);
    this->addMenu->setLayout(this->addMenuLayout);

    this->deleteMenuLayout->addRow(this->deleteSizeLabel, this->deleteSize);
    this->deleteMenuLayout->addRow(this->deleteColourLabel, this->deleteColour);
    this->deleteMenuLayout->addRow(this->deletePhotographLabel, this->deletePhotograph);
    this->deleteMenuLayout->addWidget(this->deletingBtn);
    this->deleteMenuLayout->addWidget(this->deleteExitBtn);
    this->deleteMenu->setLayout(this->deleteMenuLayout);

    this->updateMenuLayout->addRow(this->updateSizeLabel, this->updateSize);
    this->updateMenuLayout->addRow(this->updateColourLabel, this->updateColour);
    this->updateMenuLayout->addRow(this->updatePriceLabel, this->updatePrice);
    this->updateMenuLayout->addRow(this->updateQuantityLabel, this->updateQuantity);
    this->updateMenuLayout->addRow(this->updatePhotographLabel, this->updatePhotograph);
    this->updateMenuLayout->addWidget(this->updatingBtn);
    this->updateMenuLayout->addWidget(this->updateExitBtn);
    this->updateMenu->setLayout(this->updateMenuLayout);

    this->table = new QTableWidget(0,5);
    this->table->setHorizontalHeaderLabels(QStringList{ "Size","Colour","Price","Quantity","Photograph" });
    this->table->setEditTriggers(QAbstractItemView::NoEditTriggers);

    this->showMenuLayout->addWidget(this->table);
    this->showMenuLayout->addWidget(this->showExitBtn);
    this->showMenu->setLayout(this->showMenuLayout);

    QObject::connect(this->CSVBtn, &QPushButton::clicked, [&]() {
        std::shared_ptr<FileRepository> repo = std::make_shared<CSVRepository>("repo.csv",true);
        std::shared_ptr<FileRepository> shoppingRepo = std::make_shared<CSVRepository>("shoppingRepo.csv");
        this->adminController = std::make_unique<AdminController>(repo);
        this->userController = std::make_unique<UserController>(repo,shoppingRepo);
        this->repoSelector->hide();
        this->mainMenu->show();
    });

    QObject::connect(this->HTMLBtn, &QPushButton::clicked, [&]() {
        std::shared_ptr<FileRepository> repo = std::make_shared<CSVRepository>("repo.csv",true);
        std::shared_ptr<FileRepository> shoppingRepo = std::make_shared<HTMLRepository>("shoppingRepo.html");
        this->adminController = std::make_unique<AdminController>(repo);
        this->userController = std::make_unique<UserController>(repo,shoppingRepo);
        this->repoSelector->hide();
        this->mainMenu->show();
    });

    QObject::connect(this->adminBtn, &QPushButton::clicked, [&]() {
        this->mainMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->userBtn, &QPushButton::clicked, [&]() {
        this->mainMenu->hide();
        this->userMenu->show();
    });

    QObject::connect(this->adminExitBtn, &QPushButton::clicked, [&]() {
        this->adminMenu->hide();
        this->mainMenu->show();
    });

    QObject::connect(this->addBtn, &QPushButton::clicked, [&]() {
        this->adminMenu->hide();
        this->addMenu->show();
    });

    QObject::connect(this->deleteBtn, &QPushButton::clicked, [&]() {
        this->adminMenu->hide();
        this->deleteMenu->show();
    });

    QObject::connect(this->updateBtn, &QPushButton::clicked, [&]() {
        this->adminMenu->hide();
        this->updateMenu->show();
    });

    QObject::connect(this->showBtn, &QPushButton::clicked, [&]() {
        this->table->clear();
        this->table->setRowCount(0);
        this->table->setHorizontalHeaderLabels(QStringList{ "Size","Colour","Price","Quantity","Photograph" });
        for(auto item : *this->adminController->getAll())
        {
            this->table->insertRow(this->table->rowCount());
            this->table->setItem(this->table->rowCount() - 1, 0, new QTableWidgetItem(QString::number(item.size())));
            this->table->setItem(this->table->rowCount() - 1, 1, new QTableWidgetItem(QString::fromStdString(item.colour())));
            this->table->setItem(this->table->rowCount() - 1, 2, new QTableWidgetItem(QString::number(item.price())));
            this->table->setItem(this->table->rowCount() - 1, 3, new QTableWidgetItem(QString::number(item.quantity())));
            this->table->setItem(this->table->rowCount() - 1, 4, new QTableWidgetItem(QString::fromStdString(item.photograph())));
        }
        this->adminMenu->hide();
        this->showMenu->show();
    });

    QObject::connect(this->addExitBtn, &QPushButton::clicked, [&]() {
        this->addMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->deleteExitBtn, &QPushButton::clicked, [&]() {
        this->deleteMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->updateExitBtn, &QPushButton::clicked, [&]() {
        this->updateMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->showExitBtn, &QPushButton::clicked, [&]() {
        this->showMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->addingBtn, &QPushButton::clicked, [&]() {
        try {
                Validator::validate_size(this->addSize->text().toStdString());
                Validator::validate_colour(this->addColour->text().toStdString());
                Validator::validate_price(this->addPrice->text().toStdString());
                Validator::validate_quantity(this->addQuantity->text().toStdString());
                Validator::validate_photograph(this->addPhotograph->text().toStdString());
                this->adminController->add(this->addSize->text().toInt(), this->addColour->text().toStdString(), this->addPrice->text().toInt(), this->addQuantity->text().toInt(), this->addPhotograph->text().toStdString());
        }
        catch (ValidatorException& e) {
            QMessageBox::critical(this->addMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (RepoException& e) {
            QMessageBox::critical(this->addMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (AdminControllerException& e) {
            QMessageBox::critical(this->addMenu, "Error", QString::fromStdString(e.what()));
        }
        this->addMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->deletingBtn, &QPushButton::clicked, [&]() {
        try {
            Validator::validate_size(this->deleteSize->text().toStdString());
            Validator::validate_colour(this->deleteColour->text().toStdString());
            Validator::validate_photograph(this->deletePhotograph->text().toStdString());
            this->adminController->remove(this->deleteSize->text().toInt(), this->deleteColour->text().toStdString(), this->deletePhotograph->text().toStdString());
        }
        catch (ValidatorException& e) {
            QMessageBox::critical(this->deleteMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (RepoException& e) {
            QMessageBox::critical(this->deleteMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (AdminControllerException& e) {
            QMessageBox::critical(this->deleteMenu, "Error", QString::fromStdString(e.what()));
        }
        this->deleteMenu->hide();
        this->adminMenu->show();
    });

    QObject::connect(this->updatingBtn, &QPushButton::clicked, [&]() {
        int _quantity = -1;
        int _price = -1;
        try {
            Validator::validate_size(this->updateSize->text().toStdString());
            Validator::validate_colour(this->updateColour->text().toStdString());
            Validator::validate_price(this->updatePrice->text().toStdString());
            Validator::validate_quantity(this->updateQuantity->text().toStdString());
            Validator::validate_photograph(this->updatePhotograph->text().toStdString());
            if(this->updatePrice->text().toStdString()!="")
                _price = this->updatePrice->text().toInt();
            if(this->updateQuantity->text().toStdString()!="")
                _quantity = this->updateQuantity->text().toInt();
            this->adminController->update(this->updateSize->text().toInt(), this->updateColour->text().toStdString(), this->updatePrice->text().toInt(), this->updateQuantity->text().toInt(), this->updatePhotograph->text().toStdString());
        }
        catch (ValidatorException& e) {
            QMessageBox::critical(this->updateMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (RepoException& e) {
            QMessageBox::critical(this->updateMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (AdminControllerException& e) {
            QMessageBox::critical(this->updateMenu, "Error", QString::fromStdString(e.what()));
        }
        this->updateMenu->hide();
        this->adminMenu->show();
    });

    this->userShowMenu = new QWidget();
    this->userShowLayout = new QVBoxLayout();

    this->showAllBtn = new QPushButton("Show by size");
    this->openBtn = new QPushButton("Open");
    this->exitUserBtn = new QPushButton("Exit");
    this->searchBtn = new QPushButton("Search");
    this->userSize = new QLineEdit();
    this->userSize->setPlaceholderText("Size");
    this->nextBtn = new QPushButton("Next");
    this->buyBtn = new QPushButton("Buy");
    this->exitBtn = new QPushButton("Exit");

    this->userTable = new QStackedWidget();


    userMenuLayout->addWidget(this->showAllBtn);
    userMenuLayout->addWidget(this->openBtn);
    userMenuLayout->addWidget(this->exitUserBtn);

    userMenu->setLayout(userMenuLayout);

    QObject::connect(this->showAllBtn, &QPushButton::clicked, [&]() {
        this->userMenu->hide();
        this->userShowMenu->show();
    });

    QObject::connect(this->openBtn, &QPushButton::clicked, [&]() {
        this->userController->openShoppingList();
    });

    QObject::connect(this->exitUserBtn, &QPushButton::clicked, [&]() {
        this->userMenu->hide();
        this->mainMenu->show();
    });

    this->userTable->addWidget(new QLabel("No trench coats to show!"));
    this->userTable->addWidget(new QLabel("No !"));

    userShowLayout->addWidget(this->userSize);
    userShowLayout->addWidget(this->searchBtn);
    userShowLayout->addWidget(this->userTable);
    userShowLayout->addWidget(this->nextBtn);
    userShowLayout->addWidget(this->buyBtn);
    userShowLayout->addWidget(this->exitBtn);

    userShowMenu->setLayout(userShowLayout);

    this->userSize->setValidator(new QIntValidator(0, 50));

    QObject::connect(this->searchBtn, &QPushButton::clicked, [&]() {
        try {
            int size = -1;
            if (this->userSize->text().toStdString() != "")
                size = this->userSize->text().toInt();
            auto iterator = this->userController->getTrenchCarousel(size);
            if(iterator.size() == 0){
                QMessageBox::critical(this->userShowMenu, "Error", "No trench coats with the given size!");
                return;
            }
            this->userCoats = iterator;
            while(this->userTable->count() > 0)
                this->userTable->removeWidget(this->userTable->widget(0));
            for (auto& trench : iterator) {
                QWidget* widget = new QWidget();
                QHBoxLayout* layout = new QHBoxLayout();
                QLabel* sizeLabel = new QLabel(QString::fromStdString(std::to_string(trench.size())));
                QLabel* colourLabel = new QLabel(QString::fromStdString(trench.colour()));
                QLabel* priceLabel = new QLabel(QString::fromStdString(std::to_string(trench.price())));
                QLabel* quantityLabel = new QLabel(QString::fromStdString(std::to_string(trench.quantity())));
                QLabel* photographLabel = new QLabel(QString::fromStdString(trench.photograph()));
                layout->addWidget(sizeLabel);
                layout->addWidget(colourLabel);
                layout->addWidget(priceLabel);
                layout->addWidget(quantityLabel);
                layout->addWidget(photographLabel);
                widget->setLayout(layout);
                this->userTable->addWidget(widget);
            }
            this->userTable->setCurrentIndex(0);
        }
        catch (ValidatorException& e) {
            QMessageBox::critical(this->userShowMenu, "Error", QString::fromStdString(e.what()));
        }
        catch (RepoException& e) {
            QMessageBox::critical(this->userShowMenu, "Error", QString::fromStdString(e.what()));
        }
    });

    QObject::connect(this->nextBtn, &QPushButton::clicked, [&]() {
        if(this->userTable->count() == 0)
            return;
        int index = this->userTable->currentIndex();
        if(index == this->userTable->count() - 1)
            index = 0;
        else
            index++;
        this->userTable->setCurrentIndex(index);
    });
    
    QObject::connect(this->buyBtn, &QPushButton::clicked, [&]() {
        if(this->userTable->count() == 0)
            return;
        int index = this->userTable->currentIndex();
        try {
            Trench trench = this->userCoats[index];
            this->userController->addProductToShoppingList(trench);
            QMessageBox::information(this->userShowMenu, "Info", "Product added to shopping list!");
            this->searchBtn->click();
            if(index == this->userTable->count() - 1)
                index = 0;
            this->userTable->setCurrentIndex(index);
        }
        catch (RepoException& e) {
            QMessageBox::critical(this->userShowMenu, "Error", QString::fromStdString(e.what()));
        }
    });

    QObject::connect(this->exitBtn, &QPushButton::clicked, [&]() {
        this->userShowMenu->hide();
        this->userMenu->show();
    });

}

GUI::~GUI()
{
        delete repoSelector;
		delete mainMenu;
		delete adminMenu;
		delete userMenu;
		delete addMenu;
		delete deleteMenu;
		delete updateMenu;
		delete showMenu;
		delete userShowMenu;
}

void GUI::run()
{
    this->repoSelector->show();
}