// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/lang/wgsl/ast/transform/substitute_override.h"

#include <functional>
#include <utility>

#include "src/tint/lang/core/builtin_fn.h"
#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/wgsl/program/clone_context.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/lang/wgsl/sem/builtin_fn.h"
#include "src/tint/lang/wgsl/sem/index_accessor_expression.h"
#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/rtti/switch.h"

using namespace tint::core::fluent_types;  // NOLINT

TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::SubstituteOverride);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::SubstituteOverride::Config);

namespace tint::ast::transform {
namespace {

bool ShouldRun(const Program& program) {
    for (auto* node : program.AST().GlobalVariables()) {
        if (node->Is<Override>()) {
            return true;
        }
    }
    return false;
}

}  // namespace

SubstituteOverride::SubstituteOverride() = default;

SubstituteOverride::~SubstituteOverride() = default;

Transform::ApplyResult SubstituteOverride::Apply(const Program& src,
                                                 const DataMap& config,
                                                 DataMap&) const {
    ProgramBuilder b;
    program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};

    const auto* data = config.Get<Config>();
    if (!data) {
        b.Diagnostics().add_error(diag::System::Transform, "Missing override substitution data");
        return resolver::Resolve(b);
    }

    if (!ShouldRun(src)) {
        return SkipTransform;
    }

    ctx.ReplaceAll([&](const Override* w) -> const Const* {
        auto* sem = ctx.src->Sem().Get(w);

        auto source = ctx.Clone(w->source);
        auto sym = ctx.Clone(w->name->symbol);
        Type ty = w->type ? ctx.Clone(w->type) : Type{};

        // No replacement provided, just clone the override node as a const.
        auto iter = data->map.find(sem->OverrideId());
        if (iter == data->map.end()) {
            if (!w->initializer) {
                b.Diagnostics().add_error(
                    diag::System::Transform,
                    "Initializer not provided for override, and override not overridden.");
                return nullptr;
            }
            return b.Const(source, sym, ty, ctx.Clone(w->initializer));
        }

        auto value = iter->second;
        auto* ctor = Switch(
            sem->Type(),
            [&](const core::type::Bool*) { return b.Expr(!std::equal_to<double>()(value, 0.0)); },
            [&](const core::type::I32*) { return b.Expr(i32(value)); },
            [&](const core::type::U32*) { return b.Expr(u32(value)); },
            [&](const core::type::F32*) { return b.Expr(f32(value)); },
            [&](const core::type::F16*) { return b.Expr(f16(value)); });

        if (!ctor) {
            b.Diagnostics().add_error(diag::System::Transform,
                                      "Failed to create override-expression");
            return nullptr;
        }

        return b.Const(source, sym, ty, ctor);
    });

    // Ensure that objects that are indexed with an override-expression are materialized.
    // If the object is not materialized, and the 'override' variable is turned to a 'const', the
    // resulting type of the index may change. See: crbug.com/tint/1697.
    ctx.ReplaceAll([&](const IndexAccessorExpression* expr) -> const IndexAccessorExpression* {
        if (auto* sem = src.Sem().Get(expr)) {
            if (auto* access = sem->UnwrapMaterialize()->As<sem::IndexAccessorExpression>()) {
                if (access->Object()->UnwrapMaterialize()->Type()->HoldsAbstract() &&
                    access->Index()->Stage() == core::EvaluationStage::kOverride) {
                    auto* obj = b.Call(wgsl::str(wgsl::BuiltinFn::kTintMaterialize),
                                       ctx.Clone(expr->object));
                    return b.IndexAccessor(obj, ctx.Clone(expr->index));
                }
            }
        }
        return nullptr;
    });

    ctx.Clone();
    return resolver::Resolve(b);
}

SubstituteOverride::Config::Config() = default;

SubstituteOverride::Config::Config(const Config&) = default;

SubstituteOverride::Config::~Config() = default;

SubstituteOverride::Config& SubstituteOverride::Config::operator=(const Config&) = default;

}  // namespace tint::ast::transform
