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

#ifndef SKSL_DSL_FUNCTION
#define SKSL_DSL_FUNCTION

#include "include/sksl/DSLBlock.h"
#include "include/sksl/DSLExpression.h"
#include "include/sksl/DSLType.h"
#include "include/sksl/DSLVar.h"
#include "include/sksl/DSLWrapper.h"

namespace SkSL {

class Block;
class FunctionDeclaration;
class Variable;

namespace dsl {

class DSLType;

class DSLFunction {
public:
    template<class... Parameters>
    DSLFunction(const DSLType& returnType, const char* name, Parameters&... parameters) {
        SkTArray<DSLVar*> parameterArray;
        parameterArray.reserve_back(sizeof...(parameters));

        // in C++17, we could just do:
        // (parameterArray.push_back(&parameters), ...);
        int unused[] = {0, (static_cast<void>(parameterArray.push_back(&parameters)), 0)...};
        static_cast<void>(unused);
        this->init(returnType, name, std::move(parameterArray));
    }

    DSLFunction(const DSLType& returnType, const char* name, SkTArray<DSLVar*> parameters) {
        this->init(returnType, name, std::move(parameters));
    }

    DSLFunction(const SkSL::FunctionDeclaration* decl)
        : fDecl(decl) {}

    virtual ~DSLFunction() = default;

    template<class... Stmt>
    void define(Stmt... stmts) {
        DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...);
        this->define(std::move(block));
    }

    void define(DSLBlock block);

    /**
     * Invokes the function with the given arguments.
     */
    template<class... Args>
    DSLExpression operator()(Args&&... args) {
        SkTArray<DSLWrapper<DSLExpression>> argArray;
        argArray.reserve_back(sizeof...(args));
        this->collectArgs(argArray, std::forward<Args>(args)...);
        return this->call(std::move(argArray));
    }

    /**
     * Invokes the function with the given arguments.
     */
    DSLExpression call(SkTArray<DSLWrapper<DSLExpression>> args);

private:
    void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args) {}

    template<class... RemainingArgs>
    void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args, DSLVar& var,
                     RemainingArgs&&... remaining) {
        args.push_back(DSLWrapper<DSLExpression>(var));
        collectArgs(args, std::forward<RemainingArgs>(remaining)...);
    }

    template<class... RemainingArgs>
    void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args, DSLExpression expr,
                     RemainingArgs&&... remaining) {
        args.push_back(DSLWrapper<DSLExpression>(std::move(expr)));
        collectArgs(args, std::forward<RemainingArgs>(remaining)...);
    }

    void init(const DSLType& returnType, const char* name, SkTArray<DSLVar*> params);

    const SkSL::FunctionDeclaration* fDecl = nullptr;
};

} // namespace dsl

} // namespace SkSL

#endif
