#include <QMessageBox>
#include "editortrainees.h"
#include "ui_editortrainees.h"
#include "dialogeditgroup.h"
#include "dialogedittrainee.h"
#include "specialmessagebox.h"

EditorTrainees::EditorTrainees(ConnectorToServer* connectorToServer, bool adminMode, QWidget *parent) :
    TraineesView(connectorToServer, CommonView::TypeView::control, parent),
    ui(new Ui::EditorTrainees)
{
    ui->setupUi(this);    

    connect(treeWidget, &QTreeWidget::currentItemChanged, this, &EditorTrainees::on_treeWidgetCurrentItemChanged);

    ui->verticalLayout_1->addWidget(treeWidget);

    this->adminMode = adminMode;

    preparationTreeWidget();
    //setNotLoggedInVisible(true);
    loadTraineesFromDB();

    if(adminMode)
        ui->btnArchive->click();

    waitAnimationWidget->setParent(this);

    ui->btnNewGroup->setEnabled(true);
    ui->btnDeleteGroup->setEnabled(false);
    ui->btnNewTrainee->setEnabled(false);
    ui->btnDeleteTrainee->setEnabled(false);
    ui->btnToOrFromArchiveTrainee->setEnabled(false);
    ui->btnEdit->setEnabled(false);

    authComplited = true;
}

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

void EditorTrainees::closeEvent(QCloseEvent *event)
{

}

void EditorTrainees::on_btnNewGroup_clicked()
{
    Group group;
    Group group_edit;

    if(editGroup(group, &group_edit))
    {
       waitAnimationWidget->showWithPlay();
       connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_NEW_GROUP, 0, &group_edit);
    }

    return;
}

void EditorTrainees::on_btnDeleteGroup_clicked()
{
    QTreeWidgetItem *treeItemCurrent = treeWidget->currentItem();

    if(treeItemCurrent != nullptr)
    {
        QTreeWidgetItem *treeItemParent = treeItemCurrent->parent();
        if(treeItemParent == nullptr)
        {//Выбрана группа
            int id_group = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();

            if(connectorToServer->getListTraineesInGroup(id_group).count() > 0)
            {
                SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("The group is not empty.\nIt is not possible to delete a non-empty group.")).exec();
                return;
            }
            else
            {//Пустая группа
                if(SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::warningYesNo, tr("The deletion will be irrevocable.\nDelete it anyway?")).exec() == QDialog::Accepted)
                {
                    waitAnimationWidget->showWithPlay();
                    connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_DEL_GROUP, id_group);
                }
            }
        }
    }
}

void EditorTrainees::on_btnNewTrainee_clicked()
{
    QTreeWidgetItem *treeItemCurrent = treeWidget->currentItem();

    if(treeItemCurrent != nullptr)
    {
        QTreeWidgetItem *treeItemParent = treeItemCurrent->parent();
        if(treeItemParent == nullptr)
        {//Выбрана группа. Можно добавить Обучаемого
            int id_group = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();

            Trainee trainee;
            Trainee trainee_edit;

            trainee.setNeedSetPassword(true);

            if(editTrainee(trainee, &trainee_edit))
            {
               waitAnimationWidget->showWithPlay();
               connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_NEW_TRAINEE, id_group, &trainee_edit);
            }
            return;
        }
    }
}

void EditorTrainees::on_btnDeleteTrainee_clicked()
{
    QTreeWidgetItem *treeItemCurrent = treeWidget->currentItem();

    if(treeItemCurrent != nullptr)
    {
        QTreeWidgetItem *treeItemParent = treeItemCurrent->parent();
        if(treeItemParent != nullptr)
        {//Выбран обучаемый

            int id_trainee = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();
            int id_group = treeItemParent->text(ColumnsTreeUsers::clmn_ID).toInt();

            if(connectorToServer->isLoggedInTrainee(id_trainee))
            {//Обучаемый залогирован!
                SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("You cannot delete a logged-in trainee.")).exec();
                return;
            }

            if(SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::warningYesNo, tr("The deletion will be irrevocable.\nDelete it anyway?")).exec() == QDialog::Accepted)
            {
                waitAnimationWidget->showWithPlay();
                connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_DEL_TRAINEE, id_trainee);
            }
        }
    }
}

void EditorTrainees::on_btnToOrFromArchiveTrainee_clicked()
{
    QTreeWidgetItem *treeItemCurrent = treeWidget->currentItem();

    if(treeItemCurrent != nullptr)
    {
        QTreeWidgetItem *treeItemParent = treeItemCurrent->parent();
        if(treeItemParent != nullptr)
        {//Выбран обучаемый

            int id_trainee = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();

            Trainee trainee = connectorToServer->getTrainee(id_trainee);
            if(trainee.getID() == 0)
                return;

            if(connectorToServer->isArchivedTrainee(id_trainee))
            {//Архивный
                trainee.setArchived(false);
                waitAnimationWidget->showWithPlay();
                connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_EDIT_TRAINEE, id_trainee, &trainee);                
            }
            else
            {//Не Архивный                
                if(connectorToServer->isLoggedInTrainee(id_trainee))
                {//Обучаемый залогирован!
                    SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("You cannot archive a logged-in trainee.")).exec();
                    return;
                }

                trainee.setArchived(true);
                waitAnimationWidget->showWithPlay();
                connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_EDIT_TRAINEE, id_trainee, &trainee);                
                if(!archiveVisible)
                    ui->btnArchive->click();
            }
        }
    }
}

void EditorTrainees::on_btnEdit_clicked()
{
    QTreeWidgetItem *treeItemCurrent = treeWidget->currentItem();

    if(treeItemCurrent == nullptr)
        return;

    QTreeWidgetItem *treeItemParent = treeItemCurrent->parent();
    if(treeItemParent == nullptr)
    {//Выбрана группа

        int id_group = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();

        Group group = connectorToServer->getGroup(id_group);
        if(group.getID() == 0)
            return;

        Group group_edit;

        if(editGroup(group, &group_edit))
        {
            waitAnimationWidget->showWithPlay();
            connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_EDIT_GROUP, id_group, &group_edit);
        }
    }
    else
    {//Выбран обучаемый

        int id_trainee = treeItemCurrent->text(ColumnsTreeUsers::clmn_ID).toInt();

        if(connectorToServer->isLoggedInTrainee(id_trainee))
        {//Обучаемый залогирован!
            SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("You cannot edit a logged-in trainee.")).exec();
            return;
        }

        Trainee trainee = connectorToServer->getTrainee(id_trainee);
        if(trainee.getID() == 0)
            return;

        Trainee trainee_edit;

        if(editTrainee(trainee, &trainee_edit))
        {
            waitAnimationWidget->showWithPlay();
            connectorToServer->sendQueryToDB(TypeQueryToDB::TYPE_QUERY_EDIT_TRAINEE, id_trainee, &trainee_edit);
        }
    }
}

void EditorTrainees::on_btnArchive_clicked()
{
    bool state = ui->btnArchive->isChecked();
    setArchiveVisible(state);
    if(!state)
    {
        if(typeObject == TypeObject::objTrainee)
        {
            Trainee trainee = connectorToServer->getTrainee(lastCurrentID);
            if(trainee.getID())
            {
                if(trainee.getArchived())
                {
                    lastCurrentID = 0;
                    typeObject = TypeObject::objGroup;
                }
            }
            else
            {
                lastCurrentID = 0;
                typeObject = TypeObject::objGroup;
            }
        }
        else if(typeObject == TypeObject::objGroup)
        {
            Group group = connectorToServer->getGroup(lastCurrentID);
            if(group.getID())
            {}
            else
            {
                lastCurrentID = 0;
                typeObject = TypeObject::objGroup;
            }
        }
        else
        {
            lastCurrentID = 0;
            typeObject = TypeObject::objGroup;
        }
    }
    loadTraineesFromDB();
}

void EditorTrainees::on_treeWidgetCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    //Определяем доступность и функционал кнопок для выбранного элемента

    if(current == nullptr)
    {
        ui->btnNewGroup->setEnabled(true);
        ui->btnDeleteGroup->setEnabled(false);
        ui->btnNewTrainee->setEnabled(false);
        ui->btnDeleteTrainee->setEnabled(false);
        ui->btnToOrFromArchiveTrainee->setEnabled(false);
        ui->btnEdit->setEnabled(false);
        return;
    }

    QTreeWidgetItem *treeItemParent = current->parent();
    if(treeItemParent == nullptr)
    {//Выбрана группа
        int id_group = current->text(ColumnsTreeUsers::clmn_ID).toInt();

        lastCurrentID = id_group;
        typeObject = TypeObject::objGroup;

        if(adminMode)
        {
            ui->btnNewGroup->setEnabled(true);

            if(connectorToServer->getListTraineesInGroup(id_group).count() > 0)
            {//Группа не пуста
                ui->btnDeleteGroup->setEnabled(false);
            }
            else
            {//Группа пуста
                ui->btnDeleteGroup->setEnabled(true);
            }
        }
        else
        {
            ui->btnNewGroup->setEnabled(false);
            ui->btnDeleteGroup->setEnabled(false);
        }

        ui->btnNewTrainee->setEnabled(true);
        ui->btnDeleteTrainee->setEnabled(false);
        ui->btnToOrFromArchiveTrainee->setEnabled(false);
        ui->btnEdit->setEnabled(true);
        ui->btnArchive->setEnabled(true);

        ui->btnToOrFromArchiveTrainee->setText(tr("To archive"));
        ui->btnToOrFromArchiveTrainee->setIcon(QIcon(QStringLiteral(":/resources/icons/traineeArchive.png")));
    }
    else
    {//Выбран обучаемый
        int id_trainee = current->text(ColumnsTreeUsers::clmn_ID).toInt();

        lastCurrentID = id_trainee;
        typeObject = TypeObject::objTrainee;

        ui->btnNewGroup->setEnabled(false);
        ui->btnDeleteGroup->setEnabled(false);
        ui->btnNewTrainee->setEnabled(false);        

        if(connectorToServer->isArchivedTrainee(id_trainee))
        {//Архивный
            //ui->btnDeleteTrainee->setEnabled(true);

            ui->btnToOrFromArchiveTrainee->setText(tr("From archive"));
            ui->btnToOrFromArchiveTrainee->setIcon(QIcon(QStringLiteral(":/resources/icons/traineeFromArchive.png")));
        }
        else
        {//Не Архивный
            //ui->btnDeleteTrainee->setEnabled(false);

            ui->btnToOrFromArchiveTrainee->setText(tr("To archive"));
            ui->btnToOrFromArchiveTrainee->setIcon(QIcon(QStringLiteral(":/resources/icons/traineeArchive.png")));
        }

        if(connectorToServer->isLoggedInTrainee(id_trainee))
        {//Это залогированный! Удалять/Архивировать/Редактировать нельзя!
            ui->btnDeleteTrainee->setEnabled(false);
            ui->btnToOrFromArchiveTrainee->setEnabled(false);
            ui->btnEdit->setEnabled(false);
        }
        else
        {
            ui->btnToOrFromArchiveTrainee->setEnabled(true);

            if(connectorToServer->isArchivedTrainee(id_trainee))
                ui->btnDeleteTrainee->setEnabled(true);
            else
                ui->btnDeleteTrainee->setEnabled(false);

            ui->btnEdit->setEnabled(true);
        }

        //ui->btnToOrFromArchiveTrainee->setEnabled(true);

        //ui->btnEdit->setEnabled(true);
        ui->btnArchive->setEnabled(true);
    }
}

bool EditorTrainees::verifyGroup(Group group)
{
    //Проверка корректности имени

    if(group.getName() == QStringLiteral("<group>"))
    {//Имя не корректно!
        SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("Unacceptable group name has been entered.\nThe changes will not be accepted.")).exec();
        return false;
    }

    QList<Group> listGroups = connectorToServer->getListGroups();

    for(Group exist_group : listGroups)
    {
        if(group.getName() == exist_group.getName() && group.getID() != exist_group.getID())
        {//Имя уже существует
            SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("An existing group name has been entered.\nThe changes will not be accepted.")).exec();
            return false;
        }
    }

    return true;
}

bool EditorTrainees::verifyTrainee(Trainee trainee)
{
    //Проверка корректности логина, имени, пароля

    if(trainee.getName() == QStringLiteral("<name>"))
    {//Имя не корректно!
        SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("Unacceptable trainee name has been entered.\nThe changes will not be accepted.")).exec();
        return false;
    }

    if(trainee.getLogin() == QStringLiteral("<login>"))
    {//Логин не корректен!
        SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("Unacceptable trainee login has been entered.\nThe changes will not be accepted.")).exec();
        return false;
    }

    if(trainee.getPassword() == QStringLiteral("<password>"))
    {//Пароль не корректный!
        SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("Unacceptable trainee password has been entered.\nThe changes will not be accepted.")).exec();
        return false;
    }


    int user_I = connectorToServer->getIdInstructorByLogin(trainee.getLogin());
    int user_T = connectorToServer->getIdTraineeByLogin(trainee.getLogin());
    if((user_I && (user_I != trainee.getID())) ||  (user_T && (user_T != trainee.getID())))
    {//Логин уже существует!
        SpecialMessageBox(this, SpecialMessageBox::TypeSpecMsgBox::critical, tr("An existing instructor or trainee login has been entered.\nThe changes will not be accepted.")).exec();
        return 0;
    }

    return true;
}

bool EditorTrainees::editGroup(Group group, Group *group_edit)
{
    DialogEditGroup dlg(this);
    dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);

    dlg.setGroup(group);

    while (true)
    {
        switch( dlg.exec() )
        {
        case QDialog::Accepted:
        {
            *group_edit = dlg.getGroup();

            if(! verifyGroup(*group_edit))
            {
                dlg.setGroup(*group_edit);
                continue;
            }

            return true;
        }
        case QDialog::Rejected:
            return false;
        default:
            return false;
        }
    }
}

bool EditorTrainees::editTrainee(Trainee trainee, Trainee *trainee_edit)
{
    DialogEditTrainee dlg(adminMode, this);
    dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);

    dlg.setTrainee(trainee);

    while (true)
    {
        switch( dlg.exec() )
        {
        case QDialog::Accepted:
            {
                *trainee_edit = dlg.getTrainee();

                if(! verifyTrainee(*trainee_edit))
                {
                    dlg.setTrainee(*trainee_edit);
                    continue;
                }

                if(trainee_edit->getNeedSetPassword())
                {
                    //Хэшируем пароль
                    trainee_edit->hashingPassword();
                    trainee_edit->setNeedSetPassword(false);
                }

                return true;
            }
        case QDialog::Rejected:
            return false;
        default:
            return false;
        }
    }
}


