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

#include "include/sksl/DSLVar.h"

#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLType.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"

namespace SkSL {

namespace dsl {

DSLVarBase::DSLVarBase(DSLType type, skstd::string_view name, DSLExpression initialValue,
                       PositionInfo pos)
    : DSLVarBase(DSLModifiers(), std::move(type), name, std::move(initialValue), pos) {}

DSLVarBase::DSLVarBase(DSLType type, DSLExpression initialValue, PositionInfo pos)
    : DSLVarBase(type, "var", std::move(initialValue), pos) {}

DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, DSLExpression initialValue,
                       PositionInfo pos)
    : DSLVarBase(modifiers, type, "var", std::move(initialValue), pos) {}

DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, skstd::string_view name,
                       DSLExpression initialValue, PositionInfo pos)
    : fModifiers(std::move(modifiers))
    , fType(std::move(type))
    , fRawName(name)
    , fName(fType.skslType().isOpaque() ? name : DSLWriter::Name(name))
    , fInitialValue(std::move(initialValue))
    , fDeclared(DSLWriter::MarkVarsDeclared())
    , fPosition(pos) {
    if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
        if (DSLWriter::InFragmentProcessor()) {
            const SkSL::Type& skslType = type.skslType();
            GrSLType grslType;
            int count;
            if (skslType.isArray()) {
                SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(),
                                                      skslType.componentType(),
                                                      &grslType));
                count = skslType.columns();
                SkASSERT(count > 0);
            } else {
                SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(), skslType,
                                                      &grslType));
                count = 0;
            }
            const char* uniformName;
            SkASSERT(DSLWriter::CurrentEmitArgs());
            fUniformHandle = DSLWriter::CurrentEmitArgs()->fUniformHandler->addUniformArray(
                                                                 &DSLWriter::CurrentEmitArgs()->fFp,
                                                                 kFragment_GrShaderFlag,
                                                                 grslType,
                                                                 String(this->name()).c_str(),
                                                                 count,
                                                                 &uniformName).toIndex();
            fName = uniformName;
        }
#endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
    }
}

DSLVarBase::~DSLVarBase() {
    if (fDeclaration && !fDeclared) {
        DSLWriter::ReportError(String::printf("variable '%.*s' was destroyed without being "
                                              "declared",
                                              (int)fRawName.length(),
                                              fRawName.data()).c_str());
    }
}

void DSLVarBase::swap(DSLVarBase& other) {
    SkASSERT(this->storage() == other.storage());
    std::swap(fModifiers, other.fModifiers);
    std::swap(fType, other.fType);
    std::swap(fUniformHandle, other.fUniformHandle);
    std::swap(fDeclaration, other.fDeclaration);
    std::swap(fVar, other.fVar);
    std::swap(fRawName, other.fRawName);
    std::swap(fName, other.fName);
    std::swap(fInitialValue.fExpression, other.fInitialValue.fExpression);
    std::swap(fDeclared, other.fDeclared);
    std::swap(fInitialized, other.fInitialized);
    std::swap(fPosition, other.fPosition);
}

void DSLVar::swap(DSLVar& other) {
    INHERITED::swap(other);
}

VariableStorage DSLVar::storage() const {
    return VariableStorage::kLocal;
}

DSLGlobalVar::DSLGlobalVar(const char* name)
    : INHERITED(kVoid_Type, name, DSLExpression(), PositionInfo()) {
    fName = name;
    DSLWriter::MarkDeclared(*this);
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
    if (!strcmp(name, "sk_SampleCoord")) {
        fName = DSLWriter::CurrentEmitArgs()->fSampleCoord;
        // The actual sk_SampleCoord variable hasn't been created by GrGLSLFPFragmentBuilder yet, so
        // if we attempt to look it up in the symbol table we'll get null. As we are currently
        // converting all DSL code into strings rather than nodes, all we really need is a
        // correctly-named variable with the right type, so we just create a placeholder for it.
        // TODO(skia/11330): we'll need to fix this when switching over to nodes.
        const SkSL::Modifiers* modifiers = DSLWriter::Context().fModifiersPool->add(
                SkSL::Modifiers(SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
                                             /*binding=*/-1, /*index=*/-1, /*set=*/-1,
                                             SK_MAIN_COORDS_BUILTIN, /*inputAttachmentIndex=*/-1),
                                SkSL::Modifiers::kNo_Flag));

        fVar = DSLWriter::SymbolTable()->takeOwnershipOfIRNode(std::make_unique<SkSL::Variable>(
                /*offset=*/-1,
                modifiers,
                fName,
                DSLWriter::Context().fTypes.fFloat2.get(),
                /*builtin=*/true,
                SkSL::VariableStorage::kGlobal));
        fInitialized = true;
        return;
    }
#endif
    const SkSL::Symbol* result = (*DSLWriter::SymbolTable())[fName];
    SkASSERTF(result, "could not find '%.*s' in symbol table", (int)fName.length(), fName.data());
    fVar = &result->as<SkSL::Variable>();
    fInitialized = true;
}

void DSLGlobalVar::swap(DSLGlobalVar& other) {
    INHERITED::swap(other);
}

VariableStorage DSLGlobalVar::storage() const {
    return VariableStorage::kGlobal;
}

void DSLParameter::swap(DSLParameter& other) {
    INHERITED::swap(other);
}

VariableStorage DSLParameter::storage() const {
    return VariableStorage::kParameter;
}


DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) {
    return DSLExpression(*this)[std::move(index)];
}

DSLPossibleExpression DSLVarBase::assign(DSLExpression expr) {
    return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
                                    expr.release());
}

DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
    return this->assign(std::move(expr));
}

DSLPossibleExpression DSLGlobalVar::operator=(DSLExpression expr) {
    return this->assign(std::move(expr));
}

DSLPossibleExpression DSLParameter::operator=(DSLExpression expr) {
    return this->assign(std::move(expr));
}

std::unique_ptr<SkSL::Expression> DSLGlobalVar::methodCall(skstd::string_view methodName,
                                                           PositionInfo pos) {
    if (!this->fType.isEffectChild()) {
        DSLWriter::ReportError("type does not support method calls", pos);
        return nullptr;
    }
    return DSLWriter::ConvertField(DSLExpression(*this).release(), methodName);
}

DSLPossibleExpression DSLGlobalVar::eval(DSLExpression x, PositionInfo pos) {
    ExpressionArray converted;
    converted.push_back(x.release());

    auto method = this->methodCall("eval", pos);
    return DSLPossibleExpression(
            method ? DSLWriter::Call(std::move(method), std::move(converted), pos) : nullptr);
}

DSLPossibleExpression DSLGlobalVar::eval(DSLExpression x, DSLExpression y, PositionInfo pos) {
    ExpressionArray converted;
    converted.push_back(x.release());
    converted.push_back(y.release());

    auto method = this->methodCall("eval", pos);
    return DSLPossibleExpression(
            method ? DSLWriter::Call(std::move(method), std::move(converted), pos) : nullptr);
}

} // namespace dsl

} // namespace SkSL
