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

#ifndef SKSL_SYMBOLTABLE
#define SKSL_SYMBOLTABLE

#include "include/core/SkTypes.h"
#include "include/private/SkOpts_spi.h"
#include "include/private/SkSLSymbol.h"
#include "include/private/SkTHash.h"

#include <cstddef>
#include <cstdint>
#include <forward_list>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

namespace SkSL {

class Type;

/**
 * Maps identifiers to symbols.
 */
class SymbolTable {
public:
    explicit SymbolTable(bool builtin)
            : fBuiltin(builtin) {}

    explicit SymbolTable(std::shared_ptr<SymbolTable> parent, bool builtin)
            : fParent(parent)
            , fBuiltin(builtin) {}

    /** Replaces the passed-in SymbolTable with a newly-created child symbol table. */
    static void Push(std::shared_ptr<SymbolTable>* table) {
        Push(table, (*table)->isBuiltin());
    }
    static void Push(std::shared_ptr<SymbolTable>* table, bool isBuiltin) {
        *table = std::make_shared<SymbolTable>(*table, isBuiltin);
    }

    /**
     * Replaces the passed-in SymbolTable with its parent. If the child symbol table is otherwise
     * unreferenced, it will be deleted.
     */
    static void Pop(std::shared_ptr<SymbolTable>* table) {
        *table = (*table)->fParent;
    }

    /**
     * If the input is a built-in symbol table, returns a new empty symbol table as a child of the
     * input table. If the input is not a built-in symbol table, returns it as-is. Built-in symbol
     * tables must not be mutated after creation, so they must be wrapped if mutation is necessary.
     */
    static std::shared_ptr<SymbolTable> WrapIfBuiltin(std::shared_ptr<SymbolTable> symbolTable) {
        if (!symbolTable) {
            return nullptr;
        }
        if (!symbolTable->isBuiltin()) {
            return symbolTable;
        }
        return std::make_shared<SymbolTable>(std::move(symbolTable), /*builtin=*/false);
    }

    /**
     * Looks up the requested symbol and returns a const pointer.
     */
    const Symbol* find(std::string_view name) const {
        return this->lookup(MakeSymbolKey(name));
    }

    /**
     * Looks up the requested symbol, only searching the built-in symbol tables. Always const.
     */
    const Symbol* findBuiltinSymbol(std::string_view name) const;

    /**
     * Looks up the requested symbol and returns a mutable pointer. Use caution--mutating a symbol
     * will have program-wide impact, and built-in symbol tables must never be mutated.
     */
    Symbol* findMutable(std::string_view name) const {
        return this->lookup(MakeSymbolKey(name));
    }

    /**
     * Assigns a new name to the passed-in symbol. The old name will continue to exist in the symbol
     * table and point to the symbol.
     */
    void renameSymbol(Symbol* symbol, std::string_view newName);

    /**
     * Returns true if the name refers to a type (user or built-in) in the current symbol table.
     */
    bool isType(std::string_view name) const;

    /**
     * Returns true if the name refers to a builtin type.
     */
    bool isBuiltinType(std::string_view name) const;

    /**
     * Adds a symbol to this symbol table, without conferring ownership. The caller is responsible
     * for keeping the Symbol alive throughout the lifetime of the program/module.
     */
    void addWithoutOwnership(Symbol* symbol);

    /**
     * Adds a symbol to this symbol table, conferring ownership.
     */
    template <typename T>
    T* add(std::unique_ptr<T> symbol) {
        T* ptr = symbol.get();
        this->addWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol)));
        return ptr;
    }

    /**
     * Forces a symbol into this symbol table, without conferring ownership. Replaces any existing
     * symbol with the same name, if one exists.
     */
    void injectWithoutOwnership(Symbol* symbol);

    /**
     * Forces a symbol into this symbol table, conferring ownership. Replaces any existing symbol
     * with the same name, if one exists.
     */
    template <typename T>
    T* inject(std::unique_ptr<T> symbol) {
        T* ptr = symbol.get();
        this->injectWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol)));
        return ptr;
    }

    /**
     * Confers ownership of a symbol without adding its name to the lookup table.
     */
    template <typename T>
    T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
        T* ptr = symbol.get();
        fOwnedSymbols.push_back(std::move(symbol));
        return ptr;
    }

    /**
     * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol
     * table. The created array type is returned. If zero is passed, the base type is returned
     * unchanged.
     */
    const Type* addArrayDimension(const Type* type, int arraySize);

    // Call fn for every symbol in the table.  You may not mutate anything.
    template <typename Fn>
    void foreach(Fn&& fn) const {
        fSymbols.foreach(
                [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); });
    }

    size_t count() {
        return fSymbols.count();
    }

    /** Returns true if this is a built-in SymbolTable. */
    bool isBuiltin() const {
        return fBuiltin;
    }

    const std::string* takeOwnershipOfString(std::string n);

    /**
     * Indicates that this symbol table's parent is in a different module than this one.
     */
    void markModuleBoundary() {
        fAtModuleBoundary = true;
    }

    std::shared_ptr<SymbolTable> fParent;

    std::vector<std::unique_ptr<const Symbol>> fOwnedSymbols;

private:
    struct SymbolKey {
        std::string_view fName;
        uint32_t         fHash;

        bool operator==(const SymbolKey& that) const { return fName == that.fName; }
        bool operator!=(const SymbolKey& that) const { return fName != that.fName; }
        struct Hash {
            uint32_t operator()(const SymbolKey& key) const { return key.fHash; }
        };
    };

    static SymbolKey MakeSymbolKey(std::string_view name) {
        return SymbolKey{name, SkOpts::hash_fn(name.data(), name.size(), 0)};
    }

    Symbol* lookup(const SymbolKey& key) const;

    bool fBuiltin = false;
    bool fAtModuleBoundary = false;
    std::forward_list<std::string> fOwnedStrings;
    SkTHashMap<SymbolKey, Symbol*, SymbolKey::Hash> fSymbols;
};

}  // namespace SkSL

#endif
