#include "processthread.h"

#include <QTextStream>
#include <QDebug>

ProcessThread::ProcessThread(QObject *parent)
    : QThread(parent)
{
    mObjElementMap[0] = "#";
    mObjElementMap[1] = "mtllib";
    mObjElementMap[2] = "o";
    mObjElementMap[3] = "v";
    mObjElementMap[4] = "vt";
    mObjElementMap[5] = "vn";
    mObjElementMap[6] = "usemtl";
    mObjElementMap[7] = "s";
    mObjElementMap[8] = "f";

    mMtlElementMap[0] = "#";
    mMtlElementMap[1] = "newmtl";
    mMtlElementMap[2] = "Ns";
    mMtlElementMap[3] = "Ka";
    mMtlElementMap[4] = "Kd";
    mMtlElementMap[5] = "Ks";
    mMtlElementMap[6] = "Ke";
    mMtlElementMap[7] = "Ni";
    mMtlElementMap[8] = "d";
    mMtlElementMap[9] = "illum";
    mMtlElementMap[10] = "map_Kd";

    mVindex = 0;
    mVTindex = 0;
    mVNindex = 0;
}

void ProcessThread::setParam(ConfigParam p)
{
    mConfigParam = p;
}

void ProcessThread::run()
{
    mVindex = 0;
    mVTindex = 0;
    mVNindex = 0;

    QFile outputData(mConfigParam.outputPath);
    QTextStream out;
    if (outputData.open(QFile::WriteOnly | QFile::Truncate))
    {
        // QTextStream out(&outputData);
        // out << "Result: " << qSetFieldWidth(10) << left << 3.14 << 2.7;
        out.setDevice(&outputData);
    }

    QStringList list1 = mConfigParam.inputPaths;
    mConfigParam.inputPaths.clear();
    for(auto i : list1)
    {
        QFileInfo info(i);
        if(info.isFile())
        {
            if(info.suffix().compare("obj") == 0)
            {
                mConfigParam.inputPaths.append(i);
            }
        }
        else
        {
            QDir dir(i);
            traverseFolder(dir, "obj");
        }
    }


    for (int i = 0; i < mConfigParam.inputPaths.size(); i++)
    {
        int vIndexStart = 0;
        int vtIndexStart = 0;
        int vnIndexStart = 0;

        QString fileName = mConfigParam.inputPaths.at(i);
        QFile inputData(fileName);

        QString txt1 = QString("开始处理%1文件").arg(fileName);
        emit tip(txt1, 1, true);

        if (inputData.open(QFile::ReadOnly))
        {
            QTextStream input(&inputData);
            int rowIndex = 0;
            while (!input.atEnd())
            {
                // QString line;
                // input >> line;
                QString line = input.readLine().simplified();
                // QString str_first = *str.begin();

                if (line.isEmpty())
                {
                    out << "\n";
                    continue;
                }

                QStringList list = line.split(" ");
                if (!list.size())
                {
                    out << line << "\n";
                    continue;
                }

                int key = mObjElementMap.key(list.at(0), -1);
                switch (key)
                {
                case -1: // -1 目前不支持
                {
                    QString txt = QString("文件%1,%2行，未知指令%3").arg(fileName).arg(rowIndex).arg(line);
                    emit tip(txt, 2, true);
                    out << line << "\n";
                    break;
                }
                case 0: // 0 # 注释
                    out << line << "\n";
                    break;
                case 1: // 1 mtllib 材质文件
                {
                    QString outputMtl = QString("material%1.mtl").arg(i);
                    out << QString("%1 %2\n").arg(list.at(0)).arg(outputMtl);
                    processMaterialFile(fileName, list.at(1), outputMtl);
                    break;
                }
                case 2: // 2 o 模型名称
                    out << line << "\n";
                    break;
                case 3: // 3 v 顶点坐标
                    out << line << "\n";
                    mVindex++;

                    if (vIndexStart == 0)
                    {
                        vIndexStart = mVindex;
                    }

                    break;
                case 4: // 4 vt uv贴图
                    out << line << "\n";
                    mVTindex++;

                    if (vtIndexStart == 0)
                    {
                        vtIndexStart = mVTindex;
                    }

                    break;
                case 5: // 5 vn 法向量
                    out << line << "\n";
                    mVNindex++;

                    if (vnIndexStart == 0)
                    {
                        vnIndexStart = mVNindex;
                    }

                    break;
                case 6: // 6 usemtl 材质文件中定义的材质
                    out << line << "\n";
                    break;
                case 7: // 7 s off表示关闭光滑组（Smoothing group）
                    out << line << "\n";
                    break;
                case 8: // 8 f 表示由顶点、uv纹理坐标、法向量索引确定的表面
                {
                    if (list.size() != 4)
                    {
                        QString txt = QString("文件%1,%2行，%3指令异常").arg(fileName).arg(rowIndex).arg(line);
                        emit tip(txt, 2, true);
                    }
                    else
                    {
                        QString f1Str, f2Str, f3Str;
                        for (int j = 1; j < 4; j++)
                        {
                            QString str = list.at(j);
                            QStringList _list = str.split("/");
                            if (_list.size() != 3)
                            {
                                QString txt = QString("文件%1,%2行，%3指令异常").arg(fileName).arg(rowIndex).arg(line);
                                emit tip(txt, 2, true);
                                break;
                            }
                            else
                            {
                                int f1, f2, f3;
                                if (i == 0)
                                {
                                    f1 = _list.at(0).toInt();
                                    f2 = _list.at(1).toInt();
                                    f3 = _list.at(2).toInt();
                                }
                                else
                                {
                                    f1 = _list.at(0).toInt() + vIndexStart - 1;
                                    f2 = _list.at(1).toInt() + vtIndexStart - 1;
                                    f3 = _list.at(2).toInt() + vnIndexStart - 1;
                                }

                                if (j == 1)
                                {
                                    f1Str = QString("%1/%2/%3").arg(f1).arg(f2).arg(f3);
                                }
                                else if (j == 2)
                                {
                                    f2Str = QString("%1/%2/%3").arg(f1).arg(f2).arg(f3);
                                }
                                else if (j == 3)
                                {
                                    f3Str = QString("%1/%2/%3").arg(f1).arg(f2).arg(f3);
                                }
                            }
                        }
                        out << QString("f %1 %2 %3\n").arg(f1Str).arg(f2Str).arg(f3Str);
                    }
                    break;
                }
                default: // 目前不支持的属性
                {
                    QString txt = QString("文件%1,%2行，未知指令%3").arg(fileName).arg(rowIndex).arg(line);
                    emit tip(txt, 2, true);
                    out << line << "\n";
                    break;
                }
                }

                rowIndex++;
            }
            inputData.close();
        }

        QString txt2 = QString("文件%1处理完成").arg(fileName);
        emit tip(txt2, 1, true);
    }

    outputData.close();
}

bool ProcessThread::copyFile(QString srcPath, QString dstPath, bool coverFileIfExist)
{
    srcPath.replace("\\", "/");
    dstPath.replace("\\", "/");
    if (srcPath == dstPath)
    {
        return true;
    }

    if (!QFile::exists(srcPath))
    {
        // 源文件不存在
        return false;
    }

    if (QFile::exists(dstPath))
    {
        if (coverFileIfExist)
        {
            QFile::remove(dstPath);
        }
    }

    if (!QFile::copy(srcPath, dstPath))
    {
        return false;
    }
    return true;
}

bool ProcessThread::copyDirectory(const QString &srcPath, const QString &dstPath, bool coverFileIfExist)
{
    QDir srcDir(srcPath);
    QDir dstDir(dstPath);
    if (!dstDir.exists())
    {
        // 目的文件目录不存在则创建文件目录
        if (!dstDir.mkdir(dstDir.absolutePath()))
            return false;
    }
    QFileInfoList fileInfoList = srcDir.entryInfoList();
    foreach (QFileInfo fileInfo, fileInfoList)
    {
        if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        if (fileInfo.isDir())
        {
            // 当为目录时，递归的进行copy
            if (!copyDirectory(fileInfo.filePath(), dstDir.filePath(fileInfo.fileName()), coverFileIfExist))
                return false;
        }
        else
        {
            // 当允许覆盖操作时，将旧文件进行删除操作
            if (coverFileIfExist && dstDir.exists(fileInfo.fileName()))
            {
                dstDir.remove(fileInfo.fileName());
            }
            // 进行文件copy
            if (!QFile::copy(fileInfo.filePath(), dstDir.filePath(fileInfo.fileName())))
            {
                return false;
            }
        }
    }
    return true;
}

void ProcessThread::processMaterialFile(const QString &inputObj, const QString &inputMtl, const QString &outputMtl)
{
    // 拷贝材质文件到输出目录
    QFileInfo info1(inputObj), info2(mConfigParam.outputPath);
    QString mtllibFilePath1 = info1.dir().path() + "/" + inputMtl;
    QString mtllibFilePath2 = info2.dir().path() + "/" + outputMtl;
    if (!copyFile(mtllibFilePath1, mtllibFilePath2, true))
    {
        QString txt = QString("文件%1拷贝到%2失败").arg(mtllibFilePath1).arg(mtllibFilePath2);
        emit tip(txt, 2, true);
    }

    // 读取材质文件，并将其中用到的纹理图片拷贝到输出目录
    if (info1.exists())
    {
        QFile mtllibData(mtllibFilePath1);
        if (mtllibData.open(QFile::ReadOnly))
        {
            QTextStream input(&mtllibData);
            int rowIndex = 0;
            while (!input.atEnd())
            {
                QString line = input.readLine().simplified().trimmed();
                if (line.isEmpty())
                    continue;

                QStringList list = line.split(" ");
                if (!list.size())
                    continue;

                int key = mMtlElementMap.key(list.at(0), -1);
                switch (key)
                {
                case -1:
                {
                    QString txt = QString("%1文件%2行，未知关键词%3,key=%4").arg(mtllibFilePath1).arg(rowIndex).arg(line).arg(key);
                    emit tip(txt, 2, true);
                    break;
                }
                case 0: //"#"
                case 1: //"newmtl"
                case 2: //"Ns"
                case 3: //"Ka"
                case 4: //"Kd"
                case 5: //"Ks"
                case 6: //"Ke"
                case 7: //"Ni"
                case 8: //"d"
                case 9: //"illum"
                    break;
                case 10: //"map_Kd" 纹理图片
                {
                    QString imagePath1 = info1.dir().path() + "/" + list.at(1);
                    QString imagePath2 = info2.dir().path() + "/" + list.at(1);
                    QFileInfo imageInfo1(imagePath1);
                    if (!imageInfo1.exists())
                    {
                        QString txt = imagePath1 + "不存在";
                        emit tip(txt, 2, true);
                    }
                    else
                    {
                        if (!copyFile(imagePath1, imagePath2, true))
                        {
                            QString txt = QString("文件%1拷贝到%2失败").arg(imagePath1).arg(imagePath2);
                            emit tip(txt, 2, true);
                        }
                    }
                    break;
                }
                default:
                {
                    QString txt = QString("%1文件%2行，未知关键词%3,key=%4").arg(mtllibFilePath1).arg(rowIndex).arg(line).arg(key);
                    emit tip(txt, 2, true);
                    break;
                }
                }

                rowIndex++;
            }
        }
    }
}

void ProcessThread::traverseFolder(const QDir &folder, const QString& suffix)
{
    QStringList fileNames;
    // 获取文件夹中所有文件和子文件夹
    QFileInfoList list = folder.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);

    for (const QFileInfo& fileInfo : list)
    {
        if (fileInfo.isDir())
        {
            // 如果是文件夹，递归遍历
            QDir subFolder(fileInfo.absoluteFilePath());
            traverseFolder(subFolder, suffix);
        }
        else
        {
            // 如果是文件，输出文件名和路径
            if(suffix == "-1")
            {
                mConfigParam.inputPaths.append(fileInfo.absoluteFilePath());
            }
            else
            {
                QFileInfo info(fileInfo.absoluteFilePath());
                if(info.suffix().compare(suffix) == 0)
                {
                    mConfigParam.inputPaths.append(fileInfo.absoluteFilePath());
                }
            }

        }
    }
}
