MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    canUpdate=false;
    QSettings settings;
    QString dir=QFileDialog::getExistingDirectory(NULL,"Folder containing region directory",settings.value("mapfolder").toString());
    if(dir.isEmpty())
        abort();
    if(!QString(TMPDATA).endsWith("/"))
        abort();
    if(!dir.endsWith("/"))
        dir+="/";
    settings.setValue("mapfolder",dir);
    QDir().mkpath(TMPDATA);

    QDir dir2("/tmp/map-metadata/");
    dir2.setFilter(QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot);
    QFileInfoList list = dir2.entryInfoList();
    if(!QDir("/tmp/map-metadata/").exists() || list.size()==0)
    {
        process.setArguments(QStringList() << "/home/user/Desktop/CatchChallenger/datapack-pkmn/map/main/gen4/map/");
        process.setProgram("/home/user/Desktop/CatchChallenger/tools/build-map2png-Desktop-Debug/map2png");
        process.setWorkingDirectory("/tmp/map-metadata/");
        process.start();
        process.waitForFinished(999999999);
        std::cerr << process.errorString().toStdString() << std::endl;
        std::cout << process.readAll().toStdString() << std::endl;
        if(process.exitCode()!=0)
            std::cerr << "Process exit code: " << process.exitCode() << std::endl;
    }

    QString path=QCoreApplication::applicationDirPath()+"/changes.db";
    QFile destinationFile(path);
    if(!destinationFile.exists())
    {
        if(QFile::copy(":/changes.db",path))
        {
            if(!destinationFile.setPermissions(destinationFile.permissions() | QFileDevice::WriteOwner | QFileDevice::WriteUser))
                std::cerr << "Unable to set db permissions" << std::endl;
        }
        else
            std::cerr << "Unable to copy the :/changes.db" << std::endl;
    }
    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName(path);

    if (!m_db.open())
    {
        qDebug() << "Error: connection with database fail";
        abort();
    }

    QHash<QString,MapContent> db_finishedFile;
    QHash<QString,MapContent> db_not_finishedFile;
    QSqlQuery query;
    if(!query.exec("SELECT file, region, zone, subzone, name, type, finished FROM maps"))
    {
        qDebug() << query.lastError().text();
        abort();
    }
    while(query.next())
    {
        QString file = query.value(0).toString();
        MapContent mapContent;
        mapContent.region=query.value(1).toString();
        mapContent.zone=query.value(2).toString();
        mapContent.subzone=query.value(3).toString();
        mapContent.name=query.value(4).toString();
        mapContent.type=query.value(5).toString();
        if(mapContent.region.isEmpty())
            abort();
        mapContent.officialzone=query.value(7).toInt()>0;
        if(query.value(6).toInt()>0)
            db_finishedFile[file]=mapContent;
        else
            db_not_finishedFile[file]=mapContent;
    }

    {
        QDirIterator it(dir,QDirIterator::Subdirectories);
        QRegularExpression regex("\\.tmx$");
        QRegularExpression regexRemove("^/");
        while (it.hasNext()) {
            QString element=it.next();
            if(element.contains(regex))
            {
                QString sortPath=element;
                sortPath.remove(0,dir.size());
                sortPath.remove(regexRemove);
                QString pngDest=TMPDATA+sortPath;
                pngDest.replace(".tmx",".png");
                //std::cout << sortPath.toStdString() << " -> " << pngDest.toStdString() << std::endl;

                const QStringList elementList=sortPath.split("/");
                if(elementList.size()>=2 && elementList.size()<=3)
                {
                    QString file = sortPath;
                    if(db_finishedFile.contains(file))
                        finishedFile[file]=db_finishedFile.value(file);
                    else if(db_not_finishedFile.contains(file))
                        not_finishedFile[file]=db_not_finishedFile.value(file);
                    else
                    {
                        MapContent mapContent;
                        mapContent.region=elementList.at(0);
                        if(mapContent.region.isEmpty())
                            abort();
                        mapContent.zone=elementList.at(1);
                        mapContent.zone.replace(".tmx","");
                        if(elementList.size()==3)
                        {
                            mapContent.subzone=elementList.at(2);
                            mapContent.subzone.replace(".tmx","");
                        }
                        mapContent.officialzone=true;
                        //get from xml
                        QDomDocument domDocument;
                        QString xmlpath=element;
                        xmlpath.replace(".tmx",".xml");
                        QFile xmlfile(xmlpath);
                        if (xmlfile.open(QIODevice::ReadOnly))
                        {
                            if (!domDocument.setContent(&xmlfile)) {
                                xmlfile.close();
                                return;
                            }
                            xmlfile.close();

                            const tinyxml2::XMLElement root = domDocument.RootElement();
                            if(root.tagName()=="map")
                            {
                                //load the content
                                const tinyxml2::XMLElement nameItem = root.FirstChildElement("name");
                                if(!nameItem.isNull())
                                    mapContent.name=nameItem.text();

                                if(root.hasAttribute("type"))
                                    mapContent.type=root.attribute("type");
                                if(root.hasAttribute("zone"))
                                {
                                    mapContent.officialzone=true;
                                    mapContent.zone=root.attribute("zone");
                                }
                                else
                                {
                                    if(mapContent.name.startsWith("Route "))
                                    {
                                        mapContent.officialzone=false;
                                        mapContent.zone="route";
                                    }
                                    else
                                        mapContent.officialzone=true;
                                }
                            }
                        }

                        not_finishedFile[file]=mapContent;
                        //insert into database
                        QSqlQuery query;
                        if(!query.prepare("INSERT INTO maps (file, region, zone, subzone, name, type, finished) "
                                      "VALUES (:file, :region, :zone, :subzone, :name, :type, :finished)"))
                        {
                            qDebug() << query.lastError().text();
                            abort();
                        }
                        query.bindValue(":file", file);
                        query.bindValue(":region", mapContent.region);
                        query.bindValue(":zone", mapContent.zone);
                        query.bindValue(":subzone", mapContent.subzone);
                        query.bindValue(":name", mapContent.name);
                        query.bindValue(":type", mapContent.type);
                        query.bindValue(":finished", 0);
                        if(!query.exec())
                        {
                            qDebug() << query.lastError().text();
                            abort();
                        }
                    }
                }
            }
        }
    }
    preload_the_map(dir.toStdString());
    for(auto& n:map_list)
    {
        CatchChallenger::MapServer * map=n.second;
        unsigned int index=0;
        while(index<map->linked_map.size())
        {
            CatchChallenger::CommonMap * const newMap=map->linked_map.at(index);
            if(!vectorcontainsAtLeastOne(newMap->linked_map,static_cast<CatchChallenger::CommonMap *>(map)))
                newMap->linked_map.push_back(map);
            index++;
        }
    }

    displayNewNotFinishedMap();
    updateProgressLabel();
}