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

#ifndef SKSL_DEHYDRATOR
#define SKSL_DEHYDRATOR

#include "include/core/SkTypes.h"
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTHash.h"
#include "src/sksl/SkSLStringStream.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>

template <typename T> class SkSpan;

namespace SkSL {

class Expression;
class OutputStream;
class ProgramElement;
class Statement;
class Symbol;
class SymbolTable;
struct Layout;
struct Modifiers;
struct Program;

/**
 * Converts SkSL objects into a binary file. See binary_format.md for a description of the file
 * format.
 */
class Dehydrator {
public:
    Dehydrator() {
        fSymbolMap.emplace_back();
    }

    ~Dehydrator() {
        SkASSERT(fSymbolMap.size() == 1);
    }

    void write(const Program& program);

    void write(const SymbolTable& symbols);

    void write(const std::vector<std::unique_ptr<ProgramElement>>& elements);

    void finish(OutputStream& out);

    // Inserts line breaks at meaningful offsets.
    const char* prefixAtOffset(size_t byte);

private:
    void writeS8(int32_t i) {
        SkASSERT(SkTFitsIn<int8_t>(i));
        fBody.write8(i);
    }

    void writeCommand(int32_t c) {
        fCommandBreaks.add(fBody.bytesWritten());
        fBody.write8(c);
    }

    void writeU8(int32_t i) {
        SkASSERT(SkTFitsIn<uint8_t>(i));
        fBody.write8(i);
    }

    void writeS16(int32_t i) {
        SkASSERT(SkTFitsIn<int16_t>(i));
        fBody.write16(i);
    }

    void writeU16(int32_t i) {
        SkASSERT(SkTFitsIn<uint16_t>(i));
        fBody.write16(i);
    }

    void writeS32(int64_t i) {
        SkASSERT(SkTFitsIn<int32_t>(i));
        fBody.write32(i);
    }

    void writeU32(int64_t i) {
        SkASSERT(SkTFitsIn<uint32_t>(i));
        fBody.write32(i);
    }

    void allocSymbolId(const Symbol* s) {
        SkASSERT(!symbolId(s));
        fSymbolMap.back()[s] = fNextId++;
    }

    void writeId(const Symbol* s);

    uint16_t symbolId(const Symbol* s) {
        for (const auto& symbols : fSymbolMap) {
            auto found = symbols.find(s);
            if (found != symbols.end()) {
                return found->second;
            }
        }
        return 0;
    }

    void write(Layout l);

    void write(Modifiers m);

    void write(std::string_view s);

    void write(std::string s);

    void write(const ProgramElement& e);

    void write(const Expression* e);

    void write(const Statement* s);

    void write(const Symbol& s);

    void writeExpressionSpan(const SkSpan<const std::unique_ptr<Expression>>& span);

    uint16_t fNextId = 1;

    StringStream fStringBuffer;

    StringStream fBody;

    std::unordered_map<std::string, int> fStrings;

    std::vector<std::unordered_map<const Symbol*, int>> fSymbolMap;
    SkTHashSet<size_t> fStringBreaks;
    SkTHashSet<size_t> fCommandBreaks;
    size_t fStringBufferStart;
    size_t fCommandStart;

    friend class AutoDehydratorSymbolTable;
};

} // namespace SkSL

#endif
