#include "Asset/Asset_Script.h"
#include "Asset_Script.h"

void Asset_Script::Init()
{
    // 读取头建立树
    InitHeader();
    // 读取bin文件
    InitBin();
    // 读取LoadString
    InitLoadString();
}

void Asset_Script::Clear()
{
    FileInfo.clear();
    BinStringM.clear();
    LoadStringM.clear();
    _Data.clear();
    _Data.shrink_to_fit();
}

void Asset_Script::InitHeader()
{
    // 读取UUID的长度
    int UUID_LENGTH = GetInt();
    // UUID  读 1 - 36位 构造 UTF8 string
    std::string UUID = GetString(UUID_LENGTH);
    // 版本号
    int Version = GetInt();
    (void)Version;
    // 文件路径数据的大小
    int AlignedIndexHeaderSize = GetInt();
    // 解密密钥
    int IndexHeaderCrc = GetInt();
    // 文件数量
    int IndexSize = GetInt();
    // 文件起始位置
    int FristPos = tellg();
    CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc);
    int CurrPos = 0;
    StartPos = AlignedIndexHeaderSize + 56;
    // 建立pvf文件索引表
    for (int i = 0; i < IndexSize; i++)
    {
        seek(FristPos + CurrPos);
        int FileNumber = GetInt();
        (void)FileNumber;
        int FilePathLength = GetInt();
        std::string FileName = tolower(GetString(FilePathLength));
        int FileLength = GetInt();
        int Cre32 = GetInt();
        int RelativeOffset = GetInt();
        if (FileLength > 0)
        {
            int RealFileLength = (FileLength + 3) & 4294967292;
            PvfFileInfo Info;
            Info.ROffset = RelativeOffset;
            Info.Cr32 = Cre32;
            Info.Length = RealFileLength;
            Info.DecodeFlag = false;
            FileInfo[FileName] = Info;
        }
        CurrPos += 20;
        CurrPos += FilePathLength;
    }
}

void Asset_Script::InitBin()
{
    if (FileInfo.count("stringtable.bin") == 0)
    {
        SDL_LogError(0, "stringtable.bin文件不存在");
        return;
    }
    PvfFileInfo BinInfo = FileInfo["stringtable.bin"];
    seek(StartPos + BinInfo.ROffset);
    CrcDecode(BinInfo.Length, BinInfo.Cr32);
    seek(StartPos + BinInfo.ROffset);
    int FileHPos = tellg();
    int Count = GetInt();
    int CurrentIndex = 0;

    for (int i = 0; i < Count; i++)
    {
        seek(FileHPos + CurrentIndex * 4 + 4);
        int StartPos = GetInt();
        int EndPos = GetInt();
        int Len = EndPos - StartPos;
        seek(FileHPos + StartPos + 4);
        std::string Str = GetString(Len);
        BinStringM[CurrentIndex] = Str;
        CurrentIndex++;
    }
}

void Asset_Script::InitLoadString()
{
    if (FileInfo.count("n_string.lst") == 0)
    {
        SDL_LogError(0, "n_string.lst文件不存在");
    }
    PvfFileInfo Info = FileInfo["n_string.lst"];
    seek(StartPos + Info.ROffset);
    CrcDecode(Info.Length, Info.Cr32);
    seek(StartPos + Info.ROffset);

    int FileHPos = tellg();
    int Flag = GetShort();
    (void)Flag;
    int i = 2;
    while (i < Info.Length)
    {
        if ((Info.Length - i) >= 10)
        {
            seek(FileHPos + i + 6);
            int FindKey = GetInt();
            std::string Key = GetBinString(FindKey);
            std::string Type = tolower(Key.substr(0, Key.find("/")));
            if (Key.length() > 0)
            {
                PvfFileInfo *FileInfo = GetFileInfo(Key);
                if (FileInfo == nullptr)
                    continue;

                seek(StartPos + FileInfo->ROffset);
                CrcDecode(FileInfo->Length, FileInfo->Cr32);
                seek(StartPos + FileInfo->ROffset);

                std::string Str = GetStringNormal(FileInfo->Length);
                std::vector<std::string> StrArr = split(Str, "\n");
                for (auto it = StrArr.begin(); it != StrArr.end(); ++it)
                {
                    std::string strobj = *it;
                    if (strobj.find(">") != std::string::npos)
                    {
                        std::vector<std::string> strobjarr = split(strobj, ">");
                        if (strobjarr.size() > 1)
                        {
                            LoadStringM[Type][strobjarr[0]] = strobjarr[1];
                        }
                    }
                }
            }
        }
        else
            break;
        i += 10;
    }
}

std::string Asset_Script::GetBinString(int Key)
{
    if (BinStringM.count(Key))
        return BinStringM[Key];
    return "";
}

std::string Asset_Script::GetLoadString(std::string Type, std::string Key)
{
    if (LoadStringM.count(Type) && LoadStringM[Type].count(Key))
        return LoadStringM[Type][Key];
    return "";
}

Asset_Script::PvfFileInfo *Asset_Script::GetFileInfo(std::string path)
{
    path = tolower(path);
    if (FileInfo.count(path))
        return &FileInfo[path];
    return nullptr;
}

std::string Asset_Script::GetFileContent(std::string path)
{
    if (FileInfo.count(path))
    {
        seek(StartPos + FileInfo[path].ROffset);
        if (FileInfo[path].DecodeFlag == false)
        {
            CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
            seek(StartPos + FileInfo[path].ROffset);
            FileInfo[path].DecodeFlag = true;
        }
        char *blobp = new char[FileInfo[path].Length];
        read((char *)blobp, FileInfo[path].Length);
        std::string Str(blobp, FileInfo[path].Length);
        delete[] blobp;
        return Str;
    }
    return std::string();
}

char *Asset_Script::GetFileContentChar(std::string path)
{
    if (FileInfo.count(path))
    {
        seek(StartPos + FileInfo[path].ROffset);
        if (FileInfo[path].DecodeFlag == false)
        {
            CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
            seek(StartPos + FileInfo[path].ROffset);
            FileInfo[path].DecodeFlag = true;
        }
        char *blobp = new char[FileInfo[path].Length];
        read((char *)blobp, FileInfo[path].Length);
        return blobp;
    }
    return nullptr;
}
std::vector<BYTE> Asset_Script::GetFileContentByte(std::string path)
{
    if (FileInfo.count(path))
    {
        seek(StartPos + FileInfo[path].ROffset);
        if (FileInfo[path].DecodeFlag == false)
        {
            CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
            seek(StartPos + FileInfo[path].ROffset);
            FileInfo[path].DecodeFlag = true;
        }
        std::vector<BYTE> blobp(FileInfo[path].Length);
        read((char *)blobp.data(), FileInfo[path].Length);
        return blobp;
    }
    return std::vector<BYTE>();
}
