/*
WebPageMaker.cpp
Written by Matthew Fisher
*/

#include "Main.h"
#include "zip.h"

void WebPageMaker::MakeWebPage(const WebPageParameters &Parameters)
{
    if(CreateZips)
    {
        MakeZipFiles(Parameters);
    }
    else
    {
        Directory Dir(Parameters.SourceDirectory);
        for(UINT FileIndex = 0; FileIndex < Dir.Files().Length(); FileIndex++)
        {
            const String &CurFilename = Dir.Files()[FileIndex];
            if(CurFilename.EndsWith(".html"))
            {
                MakeSinglePage(Parameters, CurFilename);
            }
        }
    }

}

void WebPageMaker::MakeSinglePage(const WebPageParameters &Parameters, const String &S)
{
    Vector<String> Lines;
    String OutputFilename = Parameters.TargetDirectory + String("\\") + S;

    Utility::GetFileLines(Parameters.SourceDirectory + String("\\") + S, Lines);
    ofstream OutputFile(OutputFilename.CString());

    WebPageParser Parser;
    for(UINT LineIndex = 0; LineIndex < Lines.Length(); LineIndex++)
    {
        const String &CurLine = Lines[LineIndex];
        Parser.ParseLine(Parameters, CurLine, OutputFile);
    }
}

void WebPageMaker::MakeZipFiles(const WebPageParameters &parameters)
{
    Vector<String> lines, parts;
    Utility::GetFileLines("Zips.txt", lines, 3);

    String activeZipFilename;
    Vector<String> activeZipFiles;

    for(UINT lineIndex = 0; lineIndex < lines.Length(); lineIndex++)
    {
        const String &curLine = lines[lineIndex];
        curLine.Partition(":", parts);
        PersistentAssert(parts.Length() == 2, "Invalid line");
        if(parts[0] == "zip")
        {
            if(activeZipFilename.Length() > 0)
            {
                SaveZipFile(parameters, activeZipFilename + ".zip", activeZipFiles);
            }
            activeZipFilename = parts[1];
            activeZipFiles.FreeMemory();
        }
        else if(parts[0] == "file")
        {
            Vector<String> subParts;
            parts[1].Partition("|", subParts);
            PersistentAssert(subParts.Length() == 2, "Invalid line");

            String fileDirectory = subParts[0] + "\\";
            if(fileDirectory == ".\\")
            {
                fileDirectory.FreeMemory();
            }
            AppendFiles(parameters.ZipBaseDirectory, fileDirectory, subParts[1], activeZipFiles);
        }
        else if(parts[0] == "project")
        {
            //
            //f:.|*.props
            //f:Engine|*.*
            //f:MachineLearning|*.cpp;*.h;*.sln;*.vcxproj
            //
            const String projectDirectory = parts[1] + "\\";
            AppendFiles(parameters.ZipBaseDirectory, "", "*.props", activeZipFiles);
            AppendFiles(parameters.ZipBaseDirectory, "Engine\\", "*.*", activeZipFiles);
            AppendFiles(parameters.ZipBaseDirectory, projectDirectory, "*.cpp;*.h;*.sln;*.vcxproj;*.ps;*.vs;*.cs;*.filters;*.lib", activeZipFiles);
        }
        else
        {
            SignalError("Invalid line");
        }
    }

    if(activeZipFilename.Length() > 0)
    {
        SaveZipFile(parameters, activeZipFilename + ".zip", activeZipFiles);
    }
}

bool WebPageMaker::FilenameMatchesFilter(const String &filename, const String &filter)
{
    Vector<String> filenameParts, filterParts;
    filename.Partition(".", filenameParts);
    filter.Partition(".", filterParts);

    PersistentAssert(filterParts.Length() == 2, "Invalid filter");
    if(filenameParts.Length() != 2)
    {
        return false;
    }
    if(filterParts[0] != "*" && filterParts[0] != filenameParts[0])
    {
        return false;
    }
    if(filterParts[1] != "*" && filterParts[1] != filenameParts[1])
    {
        return false;
    }
    return true;
}

void WebPageMaker::AppendFiles(const String &baseZipDirectory, const String &fileDirectory, const String &filter, Vector<String> &files)
{
    if(filter.Contains(";"))
    {
        Vector<String> filterParts;
        filter.Partition(";", filterParts);
        for(UINT filterIndex = 0; filterIndex < filterParts.Length(); filterIndex++)
        {
            AppendFiles(baseZipDirectory, fileDirectory, filterParts[filterIndex], files);
        }
        return;
    }
    Directory dir(baseZipDirectory + fileDirectory);
    for(UINT fileIndex = 0; fileIndex < dir.Files().Length(); fileIndex++)
    {
        const String &filename = dir.Files()[fileIndex];
        if(FilenameMatchesFilter(filename, filter))
        {
            files.PushEnd(fileDirectory + filename);
        }
    }

    if(filter == "*.*")
    {
        for(UINT directoryIndex = 0; directoryIndex < dir.Directories().Length(); directoryIndex++)
        {
            const String &curDirectory = dir.Directories()[directoryIndex];
            AppendFiles(baseZipDirectory, fileDirectory + curDirectory + "\\", filter, files);
        }
    }
}

void WebPageMaker::SaveZipFile(const WebPageParameters &parameters, const String &filename, const Vector<String> &files)
{
    PersistentAssert(files.Length() > 0, "No files in zip");
    PersistentAssert(filename.Length() > 0, "Invalid zip filename");
    const String &zipDirectory = parameters.TargetDirectory + String("\\Data\\");
    HZIP zipFile = CreateZip((zipDirectory + filename).CString(), NULL);

    set<String, String::LexicographicComparison> foldersAdded;

    Console::WriteLine("Creating " + zipDirectory + filename);
    for(UINT fileIndex = 0; fileIndex < files.Length(); fileIndex++)
    {
        const String &curFilename = files[fileIndex];

        /*Vector<String> directoryParts;
        curFilename.Partition("\\", directoryParts);
        for(int pathIndex = 0; pathIndex < int(directoryParts.Length()) - 1; pathIndex++)
        {
            String folder;
            for(int innerPathIndex = 0; innerPathIndex <= pathIndex; innerPathIndex++)
            {
                folder += directoryParts[innerPathIndex] + "\\";
            }
            ZipAddFolder(zipFile, folder.CString());
        }*/

        ZipAdd(zipFile, curFilename.CString(), (parameters.ZipBaseDirectory + curFilename).CString());

        Console::WriteLine("  Adding " + curFilename);
    }
    CloseZip(zipFile);
}