#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "textFormatUtils.h"

#include <iostream>
#include <QFile>
#include <QMessageBox>
#include <QFileDialog>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QPushButton>
#include <QTimer>


using namespace std;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    notePad = new NotePad();
    connect(notePad, &NotePad::demandeSauvegarde, this, &MainWindow::recevoirSauvegarde);
    ui->ageLineEdit->setValidator(new QIntValidator(0, 999999, ui->ageLineEdit));
    ui->niveauLineEdit->setValidator(new QIntValidator(0, 999999, ui->niveauLineEdit));
    ui->tailleLineEdit->setValidator(new QDoubleValidator(0.0, 999999.0, 1,ui->tailleLineEdit));
    ui->BackPack->setHidden(true);
    ui->Edition->setHidden(true);
    ui->Fenetre->setStyleSheet("background-color: #f2f2f2;");

    QPushButton* button;
    button = new QPushButton("+", ui->Fenetre);
    button->setObjectName(QString("addFiche"));
    button->setFixedSize(35, 35);
    button->move(sizeButtonFiche*idFicheButtonCounter, 0);
    qobject_cast<QPushButton*>(ui->Fenetre->children()[0])->setStyleSheet("background-color: transparent;border:none;");
    button->show();
    connect(button, &QPushButton::clicked, this, &MainWindow::ajouter_fiche_clicked);

    for(int i=0; i<ui->menuEdition->actions().size(); i++){
        ui->menuEdition->actions()[i]->setDisabled(true);
    }
}



MainWindow::~MainWindow()
{
    delete ui;
    delete notePad;
    delete currentCharacter;
    for(Character* c : characters) {delete c;}
}



void MainWindow::loadNewCharacter(){
    QString fileName = QFileDialog::getOpenFileName(this, "Open the file");
    if(fileName.isEmpty()) return;
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Fichier non valide" + file.errorString());
        return;
    }

    file.close();

    Character* c = new Character(&file);
    createNewCharacter(c, fileName);
    currentCharacter = c;
    characters.append(c);
    currentFile = fileName;
    files.append(fileName);

}

void MainWindow::createNewCharacter(Character* p, QString s) {
    if(characters.size() == 0){
        ui->StartMenu->setHidden(true);
        ui->BackPack->setHidden(true);
        ui->Edition->setHidden(false);
    }

    delete ui->Fenetre->children().last();
    addWindow(s);
    notePad->setTexte(p->getTexteBlocNote());
    ui->BackPackPlainTextEdit->setPlainText(p->getTexteBlocNote());
    setUi(p);
    if(s.toStdString() == ""){
        currentCharacter = p;
        characters.append(p);
        currentFile = s;
        files.append(s);
    }
    for(int i=0; i<ui->Fenetre->children().size(); i++){
        QPushButton* bt = qobject_cast<QPushButton*>(ui->Fenetre->children()[i]);
        bt->setStyleSheet("background-color: #f2f2f2;");
    }
    qobject_cast<QPushButton*>(ui->Fenetre->children().last())->setStyleSheet("background-color: white;");


    int nb = ui->Fenetre->children().size();
    QPushButton* button;
    button = new QPushButton("+", ui->Fenetre);
    button->setObjectName(QString("addFiche"));
    button->setFixedSize(35, 35);
    button->move(nb*sizeButtonFiche, 0);
    qobject_cast<QPushButton*>(ui->Fenetre->children().last())->setStyleSheet("background-color: transparent;border:none;");
    button->show();
    connect(button, &QPushButton::clicked, this, &MainWindow::ajouter_fiche_clicked);

}


void MainWindow::loadImage(QString fileName) {
    QString ext[] = {"png", "jpeg", "jpg"};
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot open image: " +
                                                  file.errorString());
    }else{
        QString text = file.fileName();
        bool acceptedExt = false;
        for(QString e : ext) {
            if(text.endsWith(e)) acceptedExt = true;
        }
        if(!acceptedExt) {
            QMessageBox::warning(this, "Warning", "Format de fichier incorrect");
            return;
        }
        ui->imageLabel->setText(text);
        QPixmap px(fileName);
        ui->imageLabel->setPixmap(px);
        file.close();
    }
}

void MainWindow::saveJson(){
    QString fileName;

    int indice = 0;
    for (int i = 0; i < characters.size(); ++i) {
        if (characters[i] == currentCharacter) {
            indice = i;
        }
    }
    QPushButton* button = qobject_cast<QPushButton*>(ui->Fenetre->children()[indice]);
    if (button->objectName().toStdString() == "") {
        fileName = QFileDialog::getSaveFileName(this, "Save");
        currentFile = fileName;
    } else {
        fileName = currentFile;
    }
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
        return;
    }


    getUi();
    notePad->getUi();
    currentCharacter->setTexteBlocNote(notePad->getTexte());
    QJsonObject json;
    json["name"] = currentCharacter->getNom();
    json["age"] = currentCharacter->getAge();
    json["race"] = currentCharacter->getRace();
    json["classe"] = currentCharacter->getClasse();
    json["niveau"] = currentCharacter->getNiveau();
    json["sexe"] = currentCharacter->getSexe();
    json["taille"] = currentCharacter->getTaille();
    json["vie"] = currentCharacter->getVie();
    json["image"] = currentCharacter->getImage();
    json["blocNote"] = currentCharacter->getTexteBlocNote();
    json["backPack"] = currentCharacter->getTexteBackPack();

    QJsonArray skillsArray;
    for(int i=0; i<currentCharacter->getSkills().size(); i++){
        skillsArray.append(QJsonValue(currentCharacter->getSkills()[i]));
    }
    json["skills"] = skillsArray;
    QJsonArray skillsModArray;
    for(int i=0; i<currentCharacter->getSkillsMod().size(); i++){
        skillsModArray.append(QJsonValue(currentCharacter->getSkillsMod()[i]));
    }
    json["skillsMod"] = skillsModArray;
    QJsonArray statsArray;
    for(int i=0; i<currentCharacter->getStats().size(); i++){
        statsArray.append(QJsonValue(currentCharacter->getStats()[i]));
    }
    json["stats"] = statsArray;

    QJsonDocument doc(json);
    file.write(doc.toJson());
    file.close();
    if (button) {
        if (button->objectName() != currentFile) {
            button->setObjectName(currentFile);
            button->setText(extractFileName(currentFile));
        }
    }

}

void MainWindow::saveAsJson(){
    QString fileName = QFileDialog::getSaveFileName(this, "Save as");
    QFile file(fileName);

    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
        return;
    }
    setWindowTitle(fileName);
    currentFile = fileName;

    getUi();
    notePad->getUi();
    currentCharacter->setTexteBlocNote(notePad->getTexte());
    QJsonObject json;
    json["name"] = currentCharacter->getNom();
    json["age"] = currentCharacter->getAge();
    json["race"] = currentCharacter->getRace();
    json["classe"] = currentCharacter->getClasse();
    json["niveau"] = currentCharacter->getNiveau();
    json["sexe"] = currentCharacter->getSexe();
    json["taille"] = currentCharacter->getTaille();
    json["vie"] = currentCharacter->getVie();
    json["image"] = currentCharacter->getImage();
    json["blocNote"] = currentCharacter->getTexteBlocNote();
    json["backPack"] = currentCharacter->getTexteBackPack();

    QJsonArray skillsArray;
    for(int i=0; i<currentCharacter->getSkills().size(); i++){
        skillsArray.append(QJsonValue(currentCharacter->getSkills()[i]));
    }
    json["skills"] = skillsArray;
    QJsonArray skillsModArray;
    for(int i=0; i<currentCharacter->getSkillsMod().size(); i++){
        skillsModArray.append(QJsonValue(currentCharacter->getSkillsMod()[i]));
    }
    json["skillsMod"] = skillsModArray;
    QJsonArray statsArray;
    for(int i=0; i<currentCharacter->getStats().size(); i++){
        statsArray.append(QJsonValue(currentCharacter->getStats()[i]));
    }
    json["stats"] = statsArray;

    QJsonDocument doc(json);
    file.write(doc.toJson());
    file.close();

    int indice = 0;
    for (int i = 0; i < characters.size(); ++i) {
        if (characters[i] == currentCharacter) {
            indice = i;
        }
    }
    QPushButton* button = qobject_cast<QPushButton*>(ui->Fenetre->children()[indice]);

    if (button) {
        if (button->objectName() != currentFile) {
            button->setObjectName(currentFile);
            button->setText(extractFileName(currentFile));
        }
    }

}


void MainWindow::getUi(){
    currentCharacter->setNom(ui->nomLineEdit->text());
    currentCharacter->setAge(ui->ageLineEdit->text().toInt());
    currentCharacter->setRace(ui->raceLineEdit->text());
    currentCharacter->setClasse(ui->classeLineEdit->text());
    currentCharacter->setNiveau(ui->niveauLineEdit->text().toInt());
    currentCharacter->setSexe(ui->sexeLineEdit->text());
    currentCharacter->setTaille(ui->tailleLineEdit->text().toFloat());

    QList<int> skills;
    skills.append(ui->charismeSpinBox->value());
    skills.append(ui->dexteriteSpinBox->value());
    skills.append(ui->enduranceSpinBox->value());
    skills.append(ui->forceSpinBox->value());
    skills.append(ui->intelligenceSpinBox->value());
    skills.append(ui->sagesseSpinBox->value());
    skills.append(ui->pvSpinBox->value());
    currentCharacter->setSkills(skills);
    QList<int> skillsMod;
    skillsMod.append(ui->modCharismeSpinBox->value());
    skillsMod.append(ui->modDexteriteSpinBox->value());
    skillsMod.append(ui->modEnduranceSpinBox->value());
    skillsMod.append(ui->modForceSpinBox->value());
    skillsMod.append(ui->modIntelligenceSpinBox->value());
    skillsMod.append(ui->modSagesseSpinBox->value());
    currentCharacter->setSkills(skillsMod);
    QList<int> stats;
    for (int i = 0; i < currentCharacter->getStats().size(); ++i) {
        QString spinBoxName = QString("spinBox%1").arg(i+1);
        QSpinBox* spinBox = this->findChild<QSpinBox*>(spinBoxName);
        if (spinBox) {
            stats.append(spinBox->value());
        }
    }
    currentCharacter->setStats(stats);
    currentCharacter->setTexteBackPack(ui->BackPackPlainTextEdit->toPlainText());
}




void MainWindow::setUi(Character* p){
    ui->nomLineEdit->setText(p->getNom());
    ui->ageLineEdit->setText(QString::number(p->getAge()));
    ui->raceLineEdit->setText(p->getRace());
    ui->classeLineEdit->setText(p->getClasse());
    ui->niveauLineEdit->setText(QString::number(p->getNiveau()));
    ui->sexeLineEdit->setText(p->getSexe());
    ui->tailleLineEdit->setText(QString::number(p->getTaille()));

    ui->charismeSpinBox->setValue(p->getSkills()[0]);
    ui->dexteriteSpinBox->setValue(p->getSkills()[1]);
    ui->enduranceSpinBox->setValue(p->getSkills()[2]);
    ui->forceSpinBox->setValue(p->getSkills()[3]);
    ui->intelligenceSpinBox->setValue(p->getSkills()[4]);
    ui->sagesseSpinBox->setValue(p->getSkills()[5]);
    ui->pvSpinBox->setValue(p->getVie());

    ui->modCharismeSpinBox->setValue(p->getSkillsMod()[0]);
    ui->modDexteriteSpinBox->setValue(p->getSkillsMod()[1]);
    ui->modEnduranceSpinBox->setValue(p->getSkillsMod()[2]);
    ui->modForceSpinBox->setValue(p->getSkillsMod()[3]);
    ui->modIntelligenceSpinBox->setValue(p->getSkillsMod()[4]);
    ui->modSagesseSpinBox->setValue(p->getSkillsMod()[5]);

    for (int i = 0; i < p->getStats().size(); ++i) {
        QString spinBoxName = QString("spinBox%1").arg(i+1);
        QSpinBox* spinBox = this->findChild<QSpinBox*>(spinBoxName);
        if (spinBox) {
            spinBox->setValue(p->getStats()[i]);
        }
    }
    ui->BackPackPlainTextEdit->setPlainText(p->getTexteBackPack());
    loadImage(p->getImage());
}


void MainWindow::recevoirSauvegarde(QString contenu){
    currentCharacter->setTexteBlocNote(contenu);
    saveJson();
}

void MainWindow::toogleBackPack(){
    if(ui->BackPack->isHidden()){
        ui->Edition->setHidden(true);
        ui->BackPack->setHidden(false);
        for(int i=0; i<ui->menuEdition->actions().size(); i++){
            ui->menuEdition->actions()[i]->setDisabled(false);
        }
    }else{
        ui->BackPack->setHidden(true);
        ui->Edition->setHidden(false);
        for(int i=0; i<ui->menuEdition->actions().size(); i++){
            ui->menuEdition->actions()[i]->setDisabled(true);
        }
    }
}



void MainWindow::on_actionOuvrir_une_fiche_triggered(){this->loadNewCharacter();}
void MainWindow::on_actionNouvelle_fiche_triggered(){this->createNewCharacter(new Character());}
void MainWindow::on_actionSauvegarder_triggered(){this->saveJson();}
void MainWindow::on_actionEnregistrer_sous_triggered(){this->saveAsJson();}
void MainWindow::on_actionFermer_triggered(){QApplication::quit();}
void MainWindow::on_pushButtonNewFiche_clicked(){this->createNewCharacter(new Character());}
void MainWindow::on_pushButtonOpenFiche_clicked(){this->loadNewCharacter();}

void MainWindow::on_actionCouleur_triggered(){TextFormatUtils::changeFontColor(this);}
void MainWindow::on_actionPolice_triggered(){TextFormatUtils::changeFont(this);}
void MainWindow::on_actionTaille_triggered(){TextFormatUtils::changeFontSize(this);}
void MainWindow::on_actionGras_triggered(){TextFormatUtils::toggleBold();}
void MainWindow::on_actionItalique_triggered(){TextFormatUtils::toggleItalic();}
void MainWindow::on_actionSouligner_triggered(){TextFormatUtils::toggleUnderline();}
void MainWindow::on_actionSurligner_triggered(){TextFormatUtils::toggleOverline();}

void MainWindow::changer_fiche_clicked(){changeCurrentCharacter();}
void MainWindow::ajouter_fiche_clicked(){this->createNewCharacter(new Character());}

void MainWindow::on_imagePushButton_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, "Open the file");
    if (fileName.isEmpty()) return;
    this->loadImage(fileName);
}

void MainWindow::on_actionBloc_note_triggered(){this->notePad->show();}
void MainWindow::on_actionCaract_ristiques_triggered(){this->toogleBackPack();}

void MainWindow::addWindow(const QString& s){
    int nb = ui->Fenetre->children().size();
    int widthBar = ui->Fenetre->size().width();

    if((nb+1)*sizeButtonFiche + 35 > widthBar){
        while((nb+1)*sizeButtonFiche + 35 > widthBar){
            sizeButtonFiche--;
        }
    }
    for(int i=0; i<nb; i++){
        QWidget* widget = qobject_cast<QWidget*>(ui->Fenetre->children()[i]);
        widget->setGeometry(i*sizeButtonFiche, 0, sizeButtonFiche, 35);
        widget->show();
    }

    QPushButton* button;
    if(s == ""){
        button = new QPushButton("Sans titre", ui->Fenetre);
        button->setObjectName(QString());
    }else{
        button = new QPushButton(extractFileName(s), ui->Fenetre);
        button->setObjectName(s);
    }
    button->setGeometry(nb * sizeButtonFiche, 0, sizeButtonFiche, 35);
    button->setProperty("id", idFicheButtonCounter);
    button->show();
    connect(button, &QPushButton::clicked, this, &MainWindow::changer_fiche_clicked);



    QPushButton* closeButton = new QPushButton("X", button);
    closeButton->setFixedSize(25, 25);
    closeButton->move(button->width() - 28, (button->height()-25)/2);
    closeButton->setStyleSheet("QPushButton { font-size: 10px; padding: 0px; }");
    closeButton->raise();
    closeButton->show();
    connect(closeButton, &QPushButton::clicked, this, [=]() {
        int id = button->property("id").toInt();
        button->deleteLater();
        QTimer::singleShot(0, this, [=]() {
            int newNb = ui->Fenetre->children().size();
            for(int i=0; i<newNb; i++){
                QWidget* widget = qobject_cast<QWidget*>(ui->Fenetre->children()[i]);
                widget->setGeometry(i*sizeButtonFiche, 0, sizeButtonFiche, 35);
                widget->show();
            }
            int indice = 0;
            bool supprCurent = false;
            for(int i=0; i<characters.size(); i++){
                if(id == i){
                    if(characters[i] == currentCharacter){
                        supprCurent = true;
                        indice = i;
                        if(i+1 != characters.size()){
                            currentCharacter = characters[i+1];
                        }else if(i>0){
                            currentCharacter = characters[i-1];
                        }
                    }
                    delete characters[i];
                    characters.remove(i);
                    break;
                }
            }
            if(id == indice){
                if(supprCurent){
                    for(int i=0; i<ui->Fenetre->children().size(); i++){
                        QPushButton* bt = qobject_cast<QPushButton*>(ui->Fenetre->children()[i]);
                        bt->setStyleSheet("background-color: #f2f2f2;");
                    }
                    if(indice + 1 != files.size()){
                        currentFile = files[indice+1];
                        setUi(currentCharacter);
                        notePad->setUi(currentCharacter->getTexteBlocNote());
                        qobject_cast<QPushButton*>(ui->Fenetre->children()[indice])->setStyleSheet("background-color: white;");
                    }else if(indice>0){
                        currentFile = files[indice-1];
                        setUi(currentCharacter);
                        notePad->setUi(currentCharacter->getTexteBlocNote());
                        qobject_cast<QPushButton*>(ui->Fenetre->children()[indice-1])->setStyleSheet("background-color: white;");
                    }else{
                        toogleStartMenu();
                    }
                }
                files.remove(indice);
            }


            idFicheButtonCounter = 0;
            for(int i=0; i<ui->Fenetre->children().size()-1; i++){
                ui->Fenetre->children()[i]->setProperty("id", idFicheButtonCounter);
                idFicheButtonCounter++;
            }
        });
    });

    idFicheButtonCounter++;
}


QString MainWindow::extractFileName(QString s){
    QFileInfo infoFichier(s);
    return infoFichier.fileName();
}




void MainWindow::changeCurrentCharacter(){
    getUi();
    notePad->getUi();
    currentCharacter->setTexteBlocNote(notePad->getTexte());

    QPushButton* button = qobject_cast<QPushButton*>(sender());
    if (!button) return;
    int index = button->property("id").toInt();
    if (index >= 0 && index < characters.size()) {
        currentCharacter = characters[index];
        currentFile = files[index];
        setUi(currentCharacter);
        notePad->setUi(currentCharacter->getTexteBlocNote());
    } else {
        qWarning("ID de fiche invalide !");
    }

    for(int i=0; i<ui->Fenetre->children().size(); i++){
        QPushButton* bt = qobject_cast<QPushButton*>(ui->Fenetre->children()[i]);
        bt->setStyleSheet("background-color: #f2f2f2;");
    }
    button->setStyleSheet("background-color: white;");
}


void MainWindow::toogleStartMenu(){
    ui->BackPack->setHidden(true);
    ui->Edition->setHidden(true);
    ui->StartMenu->setHidden(false);
}


