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

#ifndef SKSL_SECTIONANDPARAMETERHELPER
#define SKSL_SECTIONANDPARAMETERHELPER

#include "SkSLErrorReporter.h"
#include "ir/SkSLProgram.h"
#include "ir/SkSLSection.h"
#include "ir/SkSLVarDeclarations.h"
#include <unordered_map>
#include <vector>

namespace SkSL {

#define CLASS_SECTION              "class"
#define CLONE_SECTION              "clone"
#define CONSTRUCTOR_SECTION        "constructor"
#define CONSTRUCTOR_CODE_SECTION   "constructorCode"
#define CONSTRUCTOR_PARAMS_SECTION "constructorParams"
#define COORD_TRANSFORM_SECTION    "coordTransform"
#define CPP_SECTION                "cpp"
#define CPP_END_SECTION            "cppEnd"
#define HEADER_SECTION             "header"
#define HEADER_END_SECTION         "headerEnd"
#define EMIT_CODE_SECTION          "emitCode"
#define FIELDS_SECTION             "fields"
#define INITIALIZERS_SECTION       "initializers"
#define MAKE_SECTION               "make"
#define OPTIMIZATION_FLAGS_SECTION "optimizationFlags"
#define SAMPLER_PARAMS_SECTION     "samplerParams"
#define SET_DATA_SECTION           "setData"
#define TEST_CODE_SECTION          "test"

class SectionAndParameterHelper {
public:
    SectionAndParameterHelper(const Program& program, ErrorReporter& errors) {
        for (const auto& p : program.fElements) {
            switch (p->fKind) {
                case ProgramElement::kVar_Kind: {
                    const VarDeclarations* decls = (const VarDeclarations*) p.get();
                    for (const auto& raw : decls->fVars) {
                        const VarDeclaration& decl = (VarDeclaration&) *raw;
                        if (IsParameter(*decl.fVar)) {
                            fParameters.push_back(decl.fVar);
                        }
                    }
                    break;
                }
                case ProgramElement::kSection_Kind: {
                    const Section* s = (const Section*) p.get();
                    if (IsSupportedSection(s->fName.c_str())) {
                        if (SectionAcceptsArgument(s->fName.c_str())) {
                            if (!s->fArgument.size()) {
                                errors.error(s->fOffset,
                                             ("section '@" + s->fName +
                                              "' requires one parameter").c_str());
                            }
                        } else if (s->fArgument.size()) {
                            errors.error(s->fOffset,
                                         ("section '@" + s->fName + "' has no parameters").c_str());
                        }
                    } else {
                        errors.error(s->fOffset,
                                     ("unsupported section '@" + s->fName + "'").c_str());
                    }
                    if (!SectionPermitsDuplicates(s->fName.c_str()) &&
                            fSections.find(s->fName) != fSections.end()) {
                        errors.error(s->fOffset,
                                     ("duplicate section '@" + s->fName + "'").c_str());
                    }
                    fSections[s->fName].push_back(s);
                    break;
                }
                default:
                    break;
            }
        }
    }

    const Section* getSection(const char* name) {
        ASSERT(!SectionPermitsDuplicates(name));
        auto found = fSections.find(name);
        if (found == fSections.end()) {
            return nullptr;
        }
        ASSERT(found->second.size() == 1);
        return found->second[0];
    }

    std::vector<const Section*> getSections(const char* name) {
        auto found = fSections.find(name);
        if (found == fSections.end()) {
            return std::vector<const Section*>();
        }
        return found->second;
    }

    const std::vector<const Variable*>& getParameters() {
        return fParameters;
    }

    static bool IsParameter(const Variable& var) {
        return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
               -1 == var.fModifiers.fLayout.fBuiltin;
    }

    static bool IsSupportedSection(const char* name) {
        return !strcmp(name, CLASS_SECTION) ||
               !strcmp(name, CLONE_SECTION) ||
               !strcmp(name, CONSTRUCTOR_SECTION) ||
               !strcmp(name, CONSTRUCTOR_CODE_SECTION) ||
               !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) ||
               !strcmp(name, COORD_TRANSFORM_SECTION) ||
               !strcmp(name, CPP_SECTION) ||
               !strcmp(name, CPP_END_SECTION) ||
               !strcmp(name, EMIT_CODE_SECTION) ||
               !strcmp(name, FIELDS_SECTION) ||
               !strcmp(name, HEADER_SECTION) ||
               !strcmp(name, HEADER_END_SECTION) ||
               !strcmp(name, INITIALIZERS_SECTION) ||
               !strcmp(name, MAKE_SECTION) ||
               !strcmp(name, OPTIMIZATION_FLAGS_SECTION) ||
               !strcmp(name, SAMPLER_PARAMS_SECTION) ||
               !strcmp(name, SET_DATA_SECTION) ||
               !strcmp(name, TEST_CODE_SECTION);
    }

    static bool SectionAcceptsArgument(const char* name) {
        return !strcmp(name, COORD_TRANSFORM_SECTION) ||
               !strcmp(name, SAMPLER_PARAMS_SECTION) ||
               !strcmp(name, SET_DATA_SECTION) ||
               !strcmp(name, TEST_CODE_SECTION);
    }

    static bool SectionPermitsDuplicates(const char* name) {
        return !strcmp(name, COORD_TRANSFORM_SECTION) ||
               !strcmp(name, SAMPLER_PARAMS_SECTION);
    }

private:
    std::vector<const Variable*> fParameters;
    std::unordered_map<String, std::vector<const Section*>> fSections;
};

} // namespace SkSL

#endif
