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

#ifndef SkSLUniformCTypes_DEFINED
#define SkSLUniformCTypes_DEFINED

#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLString.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVariable.h"

#if defined(SKSL_STANDALONE) || defined(GR_TEST_UTILS)

namespace SkSL {

// This uses templates to define dirtyExpression(), saveState() and setUniform(). Each template can
// reference token names formatted ${name} that are replaced with the actual values passed into the
// functions.
//
// dirtyExpression() and saveState() support the following tokens:
//  - ${newVar} replaced with value of newValueVarName (1st argument)
//  - ${oldVar} replaced with value of oldValueVarName (2nd argument)
//
// setUniform() supports these tokens:
//  - ${pdman} replaced with value of pdmanName (1st argument)
//  - ${uniform} replaced with value of uniformHandleName (2nd argument)
//  - ${var} replaced with value of valueVarName (3rd argument)
//
// All templates and C++ snippets should produce valid expressions, but do not need to include
// semicolons or newlines, which will be handled by the code generation itself.
class UniformCTypeMapper {
public:
    UniformCTypeMapper(Layout::CType ctype, const std::vector<String>& skslTypes,
            const String& setUniformSingleFormat, const String& setUniformArrayFormat,
            const String& defaultValue = "", const String& dirtyExpressionFormat = "",
            const String& saveStateFormat = "")
        : UniformCTypeMapper(ctype, skslTypes, setUniformSingleFormat, setUniformArrayFormat,
                true, defaultValue, dirtyExpressionFormat, saveStateFormat) { }

    // Returns nullptr if the type and layout are not supported; the returned pointer's ownership
    // is not transfered to the caller.
    //
    // The returned mapper can support tracking even if tracking is disabled based on the flags in
    // the layout.
    static const UniformCTypeMapper* Get(const Context& context, const Type& type,
                                         const Layout& layout);

    static const UniformCTypeMapper* Get(const Context& context, const Variable& variable) {
        return Get(context, variable.type(), variable.fModifiers.fLayout);
    }

    // The C++ type name that this mapper applies to
    Layout::CType ctype() const {
        return fCType;
    }

    // The sksl type names that the mapper's ctype can be mapped to
    const std::vector<String>& supportedTypeNames() const {
        return fSKSLTypes;
    }

    // Whether or not this handler knows how to write state tracking code
    // for the uniform variables
    bool supportsTracking() const {
        return fSupportsTracking;
    }

    // What the C++ class fields are initialized to in the GLSLFragmentProcessor The empty string
    // implies the no-arg constructor is suitable. This is not used if supportsTracking() returns
    // false.
    //
    // The returned snippet will be a valid as the lhs of an assignment.
    const String& defaultValue() const {
        return fDefaultValue;
    }

    // Return a boolean expression that returns true if the variables specified by newValueVarName
    // and oldValueVarName have different values. This is ignored if supportsTracking() returns
    // false.
    //
    // The returned snippet will be a valid expression to be inserted into the condition of an 'if'
    // statement.
    String dirtyExpression(const String& newValueVarName, const String& oldValueVarName) const;

    // Return a statement that stores the value of newValueVarName into the variable specified by
    // oldValueVarName. This is ignored if supportsTracking() returns false.
    //
    // The returned snippet will be a valid expression.
    String saveState(const String& newValueVarName, const String& oldValueVarName) const;

    // Return a statement that invokes the appropriate setX method on the GrGLSLProgramDataManager
    // specified by pdmanName, where the uniform is provided by the expression stored in
    // uniformHandleName, and valueVarName is the variable name pointing to the ctype instance
    // holding the new value.
    //
    // The returned snippet will be a valid expression.
    String setUniform(const String& pdmanName, const String& uniformHandleName,
                      const String& valueVarName) const;

    // True if the setUniform() template only uses the value variable once in its expression. The
    // variable does not necessarily get inlined if this returns true, since a local variable may be
    // needed if state tracking is employed for a particular uniform.
    bool canInlineUniformValue() const {
        return fInlineValue;
    }

private:
    UniformCTypeMapper(Layout::CType ctype, const std::vector<String>& skslTypes,
            const String& setUniformSingleFormat, const String& setUniformArrayFormat,
            bool enableTracking, const String& defaultValue, const String& dirtyExpressionFormat,
            const String& saveStateFormat);

    const UniformCTypeMapper* arrayMapper(int arrayCount) const;

    Layout::CType fCType;
    int fArrayCount = -1;
    std::vector<String> fSKSLTypes;
    String fUniformSingleTemplate;
    String fUniformArrayTemplate;
    bool fInlineValue; // Cached value calculated from fUniformTemplate

    bool fSupportsTracking;
    String fDefaultValue;
    String fDirtyExpressionTemplate;
    String fSaveStateTemplate;
};

}  // namespace SkSL

#endif // defined(SKSL_STANDALONE) || defined(GR_TEST_UTILS)

#endif // SkSLUniformCTypes_DEFINED
