// 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/transform/substitute_override.h"

#include <functional>

#include "src/tint/program_builder.h"
#include "src/tint/sem/variable.h"

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

namespace tint::transform {

SubstituteOverride::SubstituteOverride() = default;

SubstituteOverride::~SubstituteOverride() = default;

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

void SubstituteOverride::Run(CloneContext& ctx, const DataMap& config, DataMap&) const {
    const auto* data = config.Get<Config>();
    if (!data) {
        ctx.dst->Diagnostics().add_error(diag::System::Transform,
                                         "Missing override substitution data");
        return;
    }

    ctx.ReplaceAll([&](const ast::Override* w) -> const ast::Const* {
        auto ident = w->Identifier(ctx.src->Symbols());

        auto src = ctx.Clone(w->source);
        auto sym = ctx.Clone(w->symbol);
        auto* ty = ctx.Clone(w->type);

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

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

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

        return ctx.dst->Const(src, sym, ty, ctor);
    });

    ctx.Clone();
}

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

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

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

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

}  // namespace tint::transform
