/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "bookmaker.h"

#include "SkOSFile.h"
#include "SkOSPath.h"

bool Catalog::appendFile(const string& path) {
    FILE* file = fopen(path.c_str(), "r");
    if (!file) {
        SkDebugf("could not append %s\n", path.c_str());
        return false;
    }
    fseek(file, 0L, SEEK_END);
    int sz = (int) ftell(file);
    rewind(file);
    char* buffer = new char[sz];
    memset(buffer, ' ', sz);
    SkAssertResult(sz == (int)fread(buffer, 1, sz, file));
    fclose(file);
    this->writeBlock(sz, buffer);
    return true;
}

bool Catalog::openCatalog(const char* inDir, const char* outDir) {
    fDocsDir = inDir;
    if ('/' != fDocsDir.back()) {
        fDocsDir += '/';
    }
    string outie = outDir;
    if ('/' != outie.back()) {
        outie += '/';
    }
    fFullName = outie + "catalog.htm";
    fOut = fopen(fFullName.c_str(), "wb");
    if (!fOut) {
        SkDebugf("could not open output file %s\n", fFullName.c_str());
        return false;
    }
    fContinuation = false;
    if (!appendFile(fDocsDir + "catalogHeader.txt")) {
        return false;
    }
    this->lf(1);
    return true;
}

bool Catalog::openStatus(const char* statusFile, const char* outDir) {
    StatusIter iter(statusFile, ".bmh", StatusFilter::kInProgress);
    string unused;
    // FIXME: iterate through only chosen files by setting fDocsDir to iter
    // read one file to find directory
    if (!iter.next(&unused)) {
        return false;
    }
    return openCatalog(iter.baseDir().c_str(), outDir);
}

bool Catalog::closeCatalog() {
    if (fOut) {
        this->lf(1);
        this->writeString("}");
        this->lf(1);
        if (!appendFile(fDocsDir + "catalogTrailer.txt")) {
            return false;
        }
        this->lf(1);
        this->writePending();
        fclose(fOut);
        SkDebugf("wrote %s\n", fFullName.c_str());
        fOut = nullptr;
    }
    return true;
}

bool Catalog::parseFromFile(const char* path) {
    if (!INHERITED::parseSetup(path)) {
        return false;
    }
    fIndent = 4;
    this->writeString("var text = {");
    this->lf(1);
    fTextOut = true;
    TextParserSave save(this);
    if (!parseFiddles()) {
        return false;
    }
    this->lf(1);
    this->writeString("}");
    this->lf(2);
    this->writeString("var pngs = {");
    fTextOut = false;
    fPngOut = true;
    save.restore();
    fContinuation = false;
    return parseFiddles();
}

bool Catalog::pngOut(Definition* example) {
    string result;
    if (!fBmhParser->exampleToScript(example, BmhParser::ExampleOptions::kPng, &result)) {
        return false;
    }
    if (result.length() > 0) {
        if (fContinuation) {
            this->writeString(",");
            this->lf(1);
        } else {
            fContinuation = true;
        }
        this->writeBlock(result.size(), result.c_str());
    }
    return true;
}

bool Catalog::textOut(Definition* def, const char* stdOutStart,
    const char* stdOutEnd) {
    string result;
    if (!fBmhParser->exampleToScript(def, BmhParser::ExampleOptions::kText, &result)) {
        return false;
    }
    if (result.length() > 0) {
        if (fContinuation) {
            this->writeString(",");
            this->lf(1);
        } else {
            fContinuation = true;
        }
        fIndent = 8;
        this->writeBlock(result.size(), result.c_str());
        this->lf(1);
        this->writeString("\"stdout\": \"");
        size_t pos = 0;
        size_t len = stdOutEnd - stdOutStart;
        string example;
        const Definition* stdOut = def->hasChild(MarkType::kStdOut);
        const Definition* outVolatile = stdOut ? stdOut->hasChild(MarkType::kVolatile) : nullptr;
        if (outVolatile) {
            stdOutStart = outVolatile->fContentStart;
            while ('\n' == stdOutStart[0]) {
                ++stdOutStart;
            }
            len = stdOut->fContentEnd - stdOutStart;
        }
        while ((size_t) pos < len) {
            example += '"' == stdOutStart[pos] ? "\\\"" :
                '\\' == stdOutStart[pos] ? "\\\\" :
                '\n' == stdOutStart[pos] ? "\\\\n" :
                string(&stdOutStart[pos], 1);
            if (outVolatile && '\n' == stdOutStart[pos]) {
                ++pos;
                while ((size_t) pos < len && ' ' == stdOutStart[pos]) {
                    ++pos;
                }
                continue;
            }
            ++pos;
        }
        if (outVolatile) {
            example += "\\\\n";
        }
        this->writeBlock(example.length(), example.c_str());
        this->writeString("\"");
        this->lf(1);
        fIndent = 4;
        this->writeString("}");
    }
    return true;
}
