#include "BGImagePageFinal.h"
#include "ui_BGImagePageFinal.h"

BGImagePageFinal::BGImagePageFinal(QString appDir, QString bgImagesLocation, QWidget *parent) :
    QWizardPage(parent),
    ui(new Ui::BGImagePageFinal)
{
    ui->setupUi(this);
    this->appDir = appDir;
    this->bgImagesLocation = bgImagesLocation;
    this->oniSplitCommands = new QStringList();
    this->myOniSplitConverter = new Converter(this->appDir, this->oniSplitCommands);

    ui->lbComplete->setText("<html>The wizard is now complete. The images have been created. "
                            "You can view all created files clicking <a href=' '>here.</a><br />"
                            "<br />Click restart to create more background images from the wizard beggining, "
                            "otherwise click finish.</html>"); // Don't use rich text in qtdesigner because it generates platform dependent code

    connectSlots();
}

void BGImagePageFinal::initializePage(){
    startProcessing();
}

void BGImagePageFinal::startProcessing(){
    // page 1
    QString imagePath;
    QString imageType;
    // page 2
    bool createTXMB;
    bool createTXMP;
    QString imageCustomName;
    QString txmbName;
    QString levelId;

    imagePath = field("leImageFullPath").toString();
    imageType = field("lbImageType").toString();
    createTXMB = field("cbCreateTXMB").toBool();
    createTXMP = field("cbCreateTXMP").toBool();
    imageCustomName = field("leImageName").toString();
    txmbName = field("leTXMBName").toString();
    levelId = field("leLevelId").toString();


    QImage sourceImage(imagePath);
    QList<QString> imagesSplitted;

    // Check if images folder exists and create it if necessary
    QDir saveDir(this->bgImagesLocation);

    if(!saveDir.exists())
    {
        saveDir.mkpath("."); // http://stackoverflow.com/questions/2241808/checking-if-a-folder-exists-and-creating-folders-in-qt-c thanks Petrucio
    }

    imagesSplitted = splitIntoMultipleImages(sourceImage, imageCustomName, imageType);

    // Image divided with sucess
    if(imagesSplitted.size() > 0 && createTXMP){

        // call creations of TXMP files (oni split command)
        this->oniSplitCommands->clear();

        for(const QString &currentFile : imagesSplitted){
            this->oniSplitCommands->append("-create:txmp " + Util::String::insertQuotes(this->bgImagesLocation) + " -format:bgr32 " + Util::String::insertQuotes(currentFile));
        }

        this->myOniSplitConverter->start(); // finally process the onisplit commands
        this->myOniSplitConverter->wait(); // wait for it to complete

        if(createTXMB){

            QString txmbXmlFile = createTxmbXmlFile(imagesSplitted, txmbName, sourceImage.size(), levelId);

            if(txmbXmlFile.isEmpty())
            {
                UtilVago::showAndLogErrorPopUp("Couldn't create TXMB xml file!");
                return;
            }

            // Create TXMB oni files
            this->oniSplitCommands->clear();
            this->oniSplitCommands->append("-create " + Util::String::insertQuotes(this->bgImagesLocation) + " " + Util::String::insertQuotes(txmbXmlFile));
            this->myOniSplitConverter->start();
            this->myOniSplitConverter->wait();
        }
    }
}

QString BGImagePageFinal::createTxmbXmlFile(QList<QString> imagesSplitted, QString fileName, const QSize &imageSize, QString levelId){
    QString filePath = this->bgImagesLocation + "/" + fileName + ".xml";

    // If it's empty assume zero
    if(levelId.trimmed().isEmpty()){
        levelId = "0";
    }

    pugi::xml_document doc;

    pugi::xml_node rootNode = doc.append_child("Oni");
    pugi::xml_node txmbNode = rootNode.append_child("TXMB");
    txmbNode.append_child("Width").append_child(pugi::xml_node_type::node_pcdata).set_value(QString::number(imageSize.width()).toLatin1().data());
    txmbNode.append_child("Height").append_child(pugi::xml_node_type::node_pcdata).set_value(QString::number(imageSize.height()).toLatin1().data());
    pugi::xml_node texturesNode = txmbNode.append_child("Textures");

    for(const QString &currSplittedImage : imagesSplitted)
    {
        QFileInfo currImageFile(currSplittedImage);
        texturesNode.append_child("Link").append_child(pugi::xml_node_type::node_pcdata).set_value(QSTR_TO_CSTR(currImageFile.baseName()));
    }

    txmbNode.append_attribute("id").set_value(QSTR_TO_CSTR(levelId));

    if(!doc.save_file(QSTR_TO_CSTR(filePath))){
        return "";
    }

    return filePath;
}

// returns number of images created from the split
QList<QString> BGImagePageFinal::splitIntoMultipleImages(QImage sourceImage, QString imageName, QString imageType){

    QList<QString> splittedImages;

    QVector<int> horizontalSideSizes = getSplitSizes(sourceImage.width());

    QVector<int> verticalSideSizes = getSplitSizes(sourceImage.height());

    int currentVerticalPosition = 0;
    int currentHorizontalPosition = 0;

    for(const int currentVerticalSize : verticalSideSizes){

        for(const int currentHorizontalSize : horizontalSideSizes){

            QImage dividedImage = sourceImage.copy(currentHorizontalPosition,currentVerticalPosition,currentHorizontalSize,currentVerticalSize);
            QString currentImageId = QString::number(splittedImages.size()+1);

            // Not used. It added 0 when the number was less than 10
            //            if(currentImageId.length() == 1){
            //                currentImageId = "0" + currentImageId;
            //            }

            QString imageDestinationPath = this->bgImagesLocation + "/" + imageName + currentImageId + "." + imageType;

            if(!dividedImage.save(imageDestinationPath)){
                UtilVago::showAndLogErrorPopUp("Couldn't save image " + imageDestinationPath + "! Files weren't created correctly.");
                return QList<QString>();
            }

            currentHorizontalPosition += currentHorizontalSize;

            splittedImages.append(imageDestinationPath);
        }

        currentHorizontalPosition = 0;
        currentVerticalPosition += currentVerticalSize;
    }

    return splittedImages;
}

QVector<int> BGImagePageFinal::getSplitSizes(int imageSideSize)
{
    int remainingSideSize = imageSideSize;
    constexpr int regularSize = 256;

    QVector<int> splitSizes;

    while(remainingSideSize > 0){

        if(remainingSideSize-regularSize < 0){
            splitSizes.append(remainingSideSize);
            remainingSideSize -= remainingSideSize;
            break;
        }

        splitSizes.append(regularSize);

        remainingSideSize -= regularSize;

    }

    if(remainingSideSize != 0)
    {
        splitSizes.clear();
    }

    return splitSizes;
}

void BGImagePageFinal::openBGImagesFolder(){
    QDesktopServices::openUrl(QUrl("file:///"+this->bgImagesLocation));
}

void BGImagePageFinal::catchOniSplitProcessingErrors(QString result, int numErrors){

    if(numErrors!=0){
        QString sNumErrors=QString::number(numErrors);
        bool isWarning = false;


        if(result.startsWith("Warning: Texture")){
            isWarning = true;
        }

        if(numErrors>1){

            result = result+"\n This is the last of " + sNumErrors;

            if(!isWarning){
                result += " errors.";
            }
            else{
                result += " messages.";
            }
        }

        if(isWarning){
            UtilVago::showWarningPopUpLogButton(result);
        }
        else{
            UtilVago::showErrorPopUpLogButton(result);
        }
    }
}

void BGImagePageFinal::connectSlots(){
    connect(this->myOniSplitConverter, SIGNAL(resultConversion(QString, int)), this, SLOT(catchOniSplitProcessingErrors(QString, int)));
    connect(ui->lbComplete, SIGNAL(linkActivated(const QString & )), this, SLOT(openBGImagesFolder()));
}

BGImagePageFinal::~BGImagePageFinal()
{
    delete ui;
}
