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

#include <algorithm>
#include <string>

#include "src/tint/program_builder.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/for_loop_statement.h"
#include "src/tint/sem/variable.h"
#include "src/tint/type/atomic.h"
#include "src/tint/type/depth_multisampled_texture.h"
#include "src/tint/type/reference.h"
#include "src/tint/type/sampler.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::Transform);
TINT_INSTANTIATE_TYPEINFO(tint::transform::Data);

namespace tint::transform {

Data::Data() = default;
Data::Data(const Data&) = default;
Data::~Data() = default;
Data& Data::operator=(const Data&) = default;

DataMap::DataMap() = default;
DataMap::DataMap(DataMap&&) = default;
DataMap::~DataMap() = default;
DataMap& DataMap::operator=(DataMap&&) = default;

Output::Output() = default;
Output::Output(Program&& p) : program(std::move(p)) {}
Transform::Transform() = default;
Transform::~Transform() = default;

Output Transform::Run(const Program* src, const DataMap& data /* = {} */) const {
    Output output;
    if (auto program = Apply(src, data, output.data)) {
        output.program = std::move(program.value());
    } else {
        ProgramBuilder b;
        CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
        ctx.Clone();
        output.program = Program(std::move(b));
    }
    return output;
}

void Transform::RemoveStatement(CloneContext& ctx, const ast::Statement* stmt) {
    auto* sem = ctx.src->Sem().Get(stmt);
    if (auto* block = tint::As<sem::BlockStatement>(sem->Parent())) {
        ctx.Remove(block->Declaration()->statements, stmt);
        return;
    }
    if (TINT_LIKELY(tint::Is<sem::ForLoopStatement>(sem->Parent()))) {
        ctx.Replace(stmt, static_cast<ast::Expression*>(nullptr));
        return;
    }
    TINT_ICE(Transform, ctx.dst->Diagnostics())
        << "unable to remove statement from parent of type " << sem->TypeInfo().name;
}

const ast::Type* Transform::CreateASTTypeFor(CloneContext& ctx, const type::Type* ty) {
    if (ty->Is<type::Void>()) {
        return nullptr;
    }
    if (ty->Is<type::I32>()) {
        return ctx.dst->ty.i32();
    }
    if (ty->Is<type::U32>()) {
        return ctx.dst->ty.u32();
    }
    if (ty->Is<type::F16>()) {
        return ctx.dst->ty.f16();
    }
    if (ty->Is<type::F32>()) {
        return ctx.dst->ty.f32();
    }
    if (ty->Is<type::Bool>()) {
        return ctx.dst->ty.bool_();
    }
    if (auto* m = ty->As<type::Matrix>()) {
        auto* el = CreateASTTypeFor(ctx, m->type());
        return ctx.dst->create<ast::Matrix>(el, m->rows(), m->columns());
    }
    if (auto* v = ty->As<type::Vector>()) {
        auto* el = CreateASTTypeFor(ctx, v->type());
        return ctx.dst->create<ast::Vector>(el, v->Width());
    }
    if (auto* a = ty->As<type::Array>()) {
        auto* el = CreateASTTypeFor(ctx, a->ElemType());
        utils::Vector<const ast::Attribute*, 1> attrs;
        if (!a->IsStrideImplicit()) {
            attrs.Push(ctx.dst->create<ast::StrideAttribute>(a->Stride()));
        }
        if (a->Count()->Is<type::RuntimeArrayCount>()) {
            return ctx.dst->ty.array(el, nullptr, std::move(attrs));
        }
        if (auto* override = a->Count()->As<sem::NamedOverrideArrayCount>()) {
            auto* count = ctx.Clone(override->variable->Declaration());
            return ctx.dst->ty.array(el, count, std::move(attrs));
        }
        if (auto* override = a->Count()->As<sem::UnnamedOverrideArrayCount>()) {
            // If the array count is an unnamed (complex) override expression, then its not safe to
            // redeclare this type as we'd end up with two types that would not compare equal.
            // See crbug.com/tint/1764.
            // Look for a type alias for this array.
            for (auto* type_decl : ctx.src->AST().TypeDecls()) {
                if (auto* alias = type_decl->As<ast::Alias>()) {
                    if (ty == ctx.src->Sem().Get(alias)) {
                        // Alias found. Use the alias name to ensure types compare equal.
                        return ctx.dst->ty(ctx.Clone(alias->name->symbol));
                    }
                }
            }
            // Array is not aliased. Rebuild the array.
            auto* count = ctx.Clone(override->expr->Declaration());
            return ctx.dst->ty.array(el, count, std::move(attrs));
        }
        auto count = a->ConstantCount();
        if (TINT_UNLIKELY(!count)) {
            TINT_ICE(Transform, ctx.dst->Diagnostics()) << type::Array::kErrExpectedConstantCount;
            return ctx.dst->ty.array(el, u32(1), std::move(attrs));
        }
        return ctx.dst->ty.array(el, u32(count.value()), std::move(attrs));
    }
    if (auto* s = ty->As<sem::Struct>()) {
        return ctx.dst->ty(ctx.Clone(s->Declaration()->name->symbol));
    }
    if (auto* s = ty->As<type::Reference>()) {
        return CreateASTTypeFor(ctx, s->StoreType());
    }
    if (auto* a = ty->As<type::Atomic>()) {
        return ctx.dst->create<ast::Atomic>(CreateASTTypeFor(ctx, a->Type()));
    }
    if (auto* t = ty->As<type::DepthTexture>()) {
        return ctx.dst->ty.depth_texture(t->dim());
    }
    if (auto* t = ty->As<type::DepthMultisampledTexture>()) {
        return ctx.dst->ty.depth_multisampled_texture(t->dim());
    }
    if (ty->Is<type::ExternalTexture>()) {
        return ctx.dst->ty.external_texture();
    }
    if (auto* t = ty->As<type::MultisampledTexture>()) {
        return ctx.dst->create<ast::MultisampledTexture>(t->dim(),
                                                         CreateASTTypeFor(ctx, t->type()));
    }
    if (auto* t = ty->As<type::SampledTexture>()) {
        return ctx.dst->create<ast::SampledTexture>(t->dim(), CreateASTTypeFor(ctx, t->type()));
    }
    if (auto* t = ty->As<type::StorageTexture>()) {
        return ctx.dst->ty.storage_texture(t->dim(), t->texel_format(), t->access());
    }
    if (auto* s = ty->As<type::Sampler>()) {
        return ctx.dst->ty.sampler(s->kind());
    }
    TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
        << "Unhandled type: " << ty->TypeInfo().name;
    return nullptr;
}

}  // namespace tint::transform
