#include "soundpagefinal.h"
#include "ui_soundpagefinal.h"

SoundPageFinal::SoundPageFinal(QString AppDir, QString soundsLocation, DropTableWidget *page2Table, QHash<QString, QString> *commandMap, QWidget *parent) :
    QWizardPage(parent),
    ui(new Ui::soundpagefinal)
{
    ui->setupUi(this);
    this->soundsLocation=soundsLocation;
    this->page2Table=page2Table;
    this->commandMap=commandMap;

    this->xmlCommands = new QStringList();
    this->oniSplitCommands = new QStringList();
    this->myXmlProcessor = new XmlProcessor(AppDir, this->xmlCommands);
    this->myConverter = new Converter(AppDir,this->oniSplitCommands);

    ui->lbComplete->setText("<html>The wizard is now complete. The sounds have been converted. "
                            "You can view all converted files clicking <a href=' '>here.</a><br />"
                            "<br />Click restart to create more sounds from the wizard beggining, "
                            "otherwise click finish.</html>"); // Don't use rich text in qtdesigner because it generates platform dependent code

    connectSlots();
}

void SoundPageFinal::openSoundsFolder(){
    QString outputFolder;

    if(field("rbOther").toBool()){
        outputFolder=field("leOtherLocation").toString();
    }
    else{
        outputFolder=this->soundsLocation;
    }

    QDesktopServices::openUrl(QUrl("file:///"+outputFolder));
}

void SoundPageFinal::initializePage(){
    startProcessing();
}

void SoundPageFinal::startProcessing(){
    // Sample files names
    QString ambFile="OSBDsample_file.amb.xml";
    QString grpFile="OSBDsample_file.grp.xml";
    QString impFile="OSBDsample_file.imp.xml";
    QString ambFileLocation=GlobalVars::VagoTemporaryDir+"/"+ambFile;
    QString grpFileLocation=GlobalVars::VagoTemporaryDir+"/"+grpFile;
    QString impFileLocation=GlobalVars::VagoTemporaryDir+"/"+impFile;

    // Page 2 variables
    QString outputFolder;

    // Page 3 variables
    QString sphereRadious, minElapsedTime, maxElapsedTime, minVolumeDistance,
            maxVolumeDistance, minOcclusion, treshold, priority;
    QStringList flags;
    bool priorityLow = false, priorityNormal = false,
            priorityHigh = false, priorityHighest = false;

    bool interruptOnStop=false;
    bool playOnce=false;
    bool canPan=false;

    // Page 4 variables
    QString volume, minVolume, maxVolume, pitch, minPitch, weight, maxPitch,
            numberChannels;
    bool preventRepeat=false;
    bool stereo22=false, mono22=false, mono44Pc=false;

    // Page 5 variables
    QString minVolumeDistanceImp, maxVolumeDistanceImp, minAngleImp,
            maxAngleImp, minAttenuationImp, impactVelocityImp,
            minOcclusionImp, priorityImp;
    bool priorityLowImp = false, priorityNormalImp = false,
            priorityHighImp = false, priorityHighestImp = false;

    // Create temp folder if it doesn't exist
    if(!QDir(GlobalVars::VagoTemporaryDir).exists()){
        QDir().mkdir(GlobalVars::VagoTemporaryDir);
    }

    // Get data page 2
    if(field("rbOther").toBool()){
        outputFolder=field("leOtherLocation").toString();
    }
    else{
        outputFolder=this->soundsLocation;
    }

    // Get data page 3

    priorityLow=field("rbPriorityLow").toBool();
    priorityNormal=field("rbPriorityNormal").toBool();
    priorityHigh=field("rbPriorityHigh").toBool();
    priorityHighest=field("rbPriorityHighest").toBool();
    interruptOnStop=field("cbInterruptOnStop").toBool();
    playOnce=field("cbPlayOnce").toBool();
    canPan=field("cbCanPan").toBool();

    if(priorityNormal){
        priority="Normal";
    }
    else if(priorityLow){
        priority="Low";
    }
    else if(priorityHigh){
        priority="High";
    }
    else if(priorityHighest){
        priority="Highest";
    }

    if(interruptOnStop){
        flags << "InterruptTracksOnStop";
    }

    if(playOnce){
        flags << "PlayOnce";
    }

    if(canPan){
        flags << "CanPan";
    }

    sphereRadious=Util::String::normalizeDecimalSeparator(field("leSphereRadious").toString());
    minElapsedTime=Util::String::normalizeDecimalSeparator(field("leMinElapsedTime").toString());
    maxElapsedTime=Util::String::normalizeDecimalSeparator(field("leMaxElapsedTime").toString());
    minVolumeDistance=Util::String::normalizeDecimalSeparator(field("leMinVolumeDistance").toString());
    maxVolumeDistance=Util::String::normalizeDecimalSeparator(field("leMaxVolumeDistance").toString());
    minOcclusion=Util::String::normalizeDecimalSeparator(field("leMinOcclusion").toString());
    treshold=Util::String::normalizeDecimalSeparator(field("leTreshold").toString());

    // Get data page 4

    volume=Util::String::normalizeDecimalSeparator(field("leVolume").toString());
    minVolume=Util::String::normalizeDecimalSeparator(field("leMinVolume").toString());
    maxVolume=Util::String::normalizeDecimalSeparator(field("leMaxVolume").toString());
    pitch=Util::String::normalizeDecimalSeparator(field("lePitch").toString());
    minPitch=Util::String::normalizeDecimalSeparator(field("leMinPitch").toString());
    maxPitch=Util::String::normalizeDecimalSeparator(field("leMaxPitch").toString());
    weight=Util::String::normalizeDecimalSeparator(field("leWeight").toString());

    preventRepeat=field("cbPreventRepeat").toBool();

    stereo22=field("rbStereo22").toBool();
    mono22=field("rbMono22").toBool();
    mono44Pc=field("rbMono44Pc").toBool();

    if(stereo22 || mono44Pc){
        numberChannels="2";
    }
    else if(mono22){
        numberChannels="1";
    }

    // Get data page 5
    priorityLowImp=field("rbPriorityLowImp").toBool();
    priorityNormalImp=field("rbPriorityNormalImp").toBool();
    priorityHighImp=field("rbPriorityHighImp").toBool();
    priorityHighestImp=field("rbPriorityHighestImp").toBool();

    if(priorityNormalImp){
        priorityImp="Normal";
    }
    else if(priorityLowImp){
        priorityImp="Low";
    }
    else if(priorityHighImp){
        priorityImp="High";
    }
    else if(priorityHighestImp){
        priorityImp="Highest";
    }

    minVolumeDistanceImp=Util::String::normalizeDecimalSeparator(field("leMinVolumeDistanceImp").toString());
    maxVolumeDistanceImp=Util::String::normalizeDecimalSeparator(field("leMaxVolumeDistanceImp").toString());
    minAngleImp=Util::String::normalizeDecimalSeparator(field("leMinAngleImp").toString());
    maxAngleImp=Util::String::normalizeDecimalSeparator(field("leMaxAngleImp").toString());
    minAttenuationImp=Util::String::normalizeDecimalSeparator(field("leMinAttenuationImp").toString());
    impactVelocityImp=Util::String::normalizeDecimalSeparator(field("leImpactVelocityImp").toString());
    minOcclusionImp=Util::String::normalizeDecimalSeparator(field("leMinOcclusionImp").toString());

    //######################################################### Starting xml processing

    // Clean tmp dir
    if(!Util::FileSystem::rmDir(GlobalVars::VagoTemporaryDir)){
        UtilVago::showAndLogErrorPopUpLogButton("Couldn't clean vago temp dir for complete sound wizard. Aborting.\n"+GlobalVars::VagoTemporaryDir);
        return;
    }

    if(!QDir(QDir::tempPath()).mkpath("VagoTemp")){
        UtilVago::showAndLogErrorPopUpLogButton("Couldn't reconstruct vago temp dir for complete sound wizard. Aborting.\n"+GlobalVars::VagoTemporaryDir);
    }

    // Copy sample xml files to tmp dir
    QFile::copy(":/new/sampleFiles/"+ambFile , ambFileLocation);
    QFile::copy(":/new/sampleFiles/"+grpFile , grpFileLocation);
    QFile::copy(":/new/sampleFiles/"+impFile , impFileLocation);
    QFile::setPermissions(ambFileLocation, QFile::ReadOwner | QFile::WriteOwner); //remove read only attribute that come from resources
    QFile::setPermissions(grpFileLocation, QFile::ReadOwner | QFile::WriteOwner);
    QFile::setPermissions(impFileLocation, QFile::ReadOwner | QFile::WriteOwner);

    (*this->xmlCommands)
     << "--replace-all-values -e Priority -n "+Util::String::insertQuotes(priority)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e Flags -n "+(flags.join(" ").isEmpty() ? Util::String::insertQuotes("") : Util::String::insertQuotes(flags.join(" ")))+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e SphereRadius -n "+Util::String::insertQuotes(sphereRadious)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e Treshold -n "+Util::String::insertQuotes(treshold)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e MinOcclusion -n "+Util::String::insertQuotes(minOcclusion)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name ElapsedTime -e  Max -n "+Util::String::insertQuotes(maxElapsedTime)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name ElapsedTime -e  Min -n "+Util::String::insertQuotes(minElapsedTime)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Distance -e  Max -n "+Util::String::insertQuotes(maxVolumeDistance)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Distance -e  Min -n "+Util::String::insertQuotes(minVolumeDistance)+" -f "+Util::String::insertQuotes(ambFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name SoundGroup -e  Volume -n "+Util::String::insertQuotes(volume)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name SoundGroup -e  Pitch -n "+Util::String::insertQuotes(pitch)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name SoundGroup -e  NumberOfChannels -n "+Util::String::insertQuotes(numberChannels)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Volume -e  Min -n "+Util::String::insertQuotes(minVolume)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Volume -e  Max -n "+Util::String::insertQuotes(maxVolume)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Pitch -e  Min -n "+Util::String::insertQuotes(minPitch)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Pitch -e  Max -n "+Util::String::insertQuotes(maxPitch)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e  Weight -n "+Util::String::insertQuotes(weight)+" -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e  Priority -n "+Util::String::insertQuotes(priorityImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Distance -e  Min -n "+Util::String::insertQuotes(minVolumeDistanceImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Distance -e  Max -n "+Util::String::insertQuotes(maxVolumeDistanceImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Angle -e  Min -n "+Util::String::insertQuotes(minAngleImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values --parent-element-name Angle -e  Max -n "+Util::String::insertQuotes(maxAngleImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e  MinAttenuation -n "+Util::String::insertQuotes(minAttenuationImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e  ImpactVelocity -n "+Util::String::insertQuotes(impactVelocityImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose"
     << "--replace-all-values -e  MinOcclusion -n "+Util::String::insertQuotes(minOcclusionImp)+" -f "+Util::String::insertQuotes(impFileLocation)+" --no-backups --no-verbose";

    if(preventRepeat){
        (*this->xmlCommands) << "--replace-all-values --parent-element-name SoundGroup -e Flags -n PreventRepeat -f "+Util::String::insertQuotes(grpFileLocation)+" --no-backups --no-verbose";
    }

    myXmlProcessor->start();
    myXmlProcessor->wait(); // Wait until all xml is edited

    QString currFileName;
    QString currGrpFileLocation;
    QString currAmbFileLocation;
    QString currImpFileLocation;

    for(int i=0; i<this->page2Table->rowCount(); i++){

        (*this->oniSplitCommands) << this->commandMap->value("xml->XML->ONI")+" "+Util::String::insertQuotes(outputFolder)+" "+Util::String::insertQuotes(this->page2Table->item(i,1)->text()); // add location of sound file to convert

        currFileName=this->page2Table->item(i,0)->text(); // get current file name
        currAmbFileLocation = outputFolder + "/" + QString(ambFile).replace("sample_file",currFileName); // get the new files, filenames
        currGrpFileLocation = outputFolder + "/" + QString(grpFile).replace("sample_file",currFileName);
        currImpFileLocation = outputFolder + "/" + QString(impFile).replace("sample_file",currFileName);

        QFile::copy(ambFileLocation, currAmbFileLocation); // make a copy of the sample files that will be the real files
        QFile::copy(grpFileLocation, currGrpFileLocation);
        QFile::copy(impFileLocation, currImpFileLocation);

        (*this->xmlCommands) << "--replace-all-values -e BaseTrack1 -n "+Util::String::insertQuotes(currFileName)+" -f "+Util::String::insertQuotes(currAmbFileLocation)+" --no-backups --no-verbose" // process the xml
                             << "--replace-all-values -e Sound -n "+Util::String::insertQuotes(currFileName)+" -f "+Util::String::insertQuotes(currGrpFileLocation)+" --no-backups --no-verbose"
                             << "--replace-all-values -e Group -n "+Util::String::insertQuotes(currFileName)+" -f "+Util::String::insertQuotes(currImpFileLocation)+" --no-backups --no-verbose";

        myXmlProcessor->start();
        myXmlProcessor->wait(); // Wait until all xml is edited

        (*this->oniSplitCommands) << this->commandMap->value("xml->XML->ONI")+" "+Util::String::insertQuotes(outputFolder)+" "+Util::String::insertQuotes(currAmbFileLocation);
        (*this->oniSplitCommands) << this->commandMap->value("xml->XML->ONI")+" "+Util::String::insertQuotes(outputFolder)+" "+Util::String::insertQuotes(currGrpFileLocation);
        (*this->oniSplitCommands) << this->commandMap->value("xml->XML->ONI")+" "+Util::String::insertQuotes(outputFolder)+" "+Util::String::insertQuotes(currImpFileLocation);
    }

    this->myConverter->start(); // finally process the onisplit commands
    this->myConverter->wait(); // wait for it to complete
}

void SoundPageFinal::catchXmlAndOSplitProcessingError(QString result, int numErrors){

    if(numErrors!=0){
        QString sNumErrors=QString::number(numErrors);
        if(numErrors>1){
            UtilVago::showErrorPopUpLogButton(result+"\n This is the last of " + sNumErrors + " errors.");
        }
        else{
            UtilVago::showErrorPopUpLogButton(result);
        }
    }
}

void SoundPageFinal::connectSlots(){
    //This signal is for thread that is working setup the progress bar (make it visible and set it's min-max)
    connect(this->myXmlProcessor, SIGNAL(resultConversion(QString, int)), this, SLOT(catchXmlAndOSplitProcessingError(QString, int)));
    connect(this->myConverter, SIGNAL(resultConversion(QString, int)), this, SLOT(catchXmlAndOSplitProcessingError(QString, int)));
    connect(ui->lbComplete, SIGNAL(linkActivated(const QString & )), this, SLOT(openSoundsFolder()));
}

SoundPageFinal::~SoundPageFinal()
{
    delete this->xmlCommands;
    delete this->oniSplitCommands;
    delete this->myXmlProcessor;
    delete this->myConverter;
    delete ui;
}
