// Copyright 2021 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/program_builder.h"

#include "src/tint/ast/assignment_statement.h"
#include "src/tint/ast/call_statement.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/debug.h"
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/value_expression.h"
#include "src/tint/sem/variable.h"
#include "src/tint/switch.h"
#include "src/tint/utils/compiler_macros.h"

using namespace tint::number_suffixes;  // NOLINT

namespace tint {

ProgramBuilder::VarOptions::~VarOptions() = default;
ProgramBuilder::LetOptions::~LetOptions() = default;
ProgramBuilder::ConstOptions::~ConstOptions() = default;
ProgramBuilder::OverrideOptions::~OverrideOptions() = default;

ProgramBuilder::ProgramBuilder()
    : id_(ProgramID::New()),
      ast_(ast_nodes_.Create<ast::Module>(id_, AllocateNodeID(), Source{})) {}

ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs)
    : id_(std::move(rhs.id_)),
      last_ast_node_id_(std::move(rhs.last_ast_node_id_)),
      types_(std::move(rhs.types_)),
      ast_nodes_(std::move(rhs.ast_nodes_)),
      sem_nodes_(std::move(rhs.sem_nodes_)),
      ast_(std::move(rhs.ast_)),
      sem_(std::move(rhs.sem_)),
      symbols_(std::move(rhs.symbols_)),
      diagnostics_(std::move(rhs.diagnostics_)) {
    rhs.MarkAsMoved();
}

ProgramBuilder::~ProgramBuilder() = default;

ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) {
    rhs.MarkAsMoved();
    AssertNotMoved();
    id_ = std::move(rhs.id_);
    last_ast_node_id_ = std::move(rhs.last_ast_node_id_);
    types_ = std::move(rhs.types_);
    ast_nodes_ = std::move(rhs.ast_nodes_);
    sem_nodes_ = std::move(rhs.sem_nodes_);
    ast_ = std::move(rhs.ast_);
    sem_ = std::move(rhs.sem_);
    symbols_ = std::move(rhs.symbols_);
    diagnostics_ = std::move(rhs.diagnostics_);

    return *this;
}

ProgramBuilder ProgramBuilder::Wrap(const Program* program) {
    ProgramBuilder builder;
    builder.id_ = program->ID();
    builder.last_ast_node_id_ = program->HighestASTNodeID();
    builder.types_ = type::Manager::Wrap(program->Types());
    builder.ast_ =
        builder.create<ast::Module>(program->AST().source, program->AST().GlobalDeclarations());
    builder.sem_ = sem::Info::Wrap(program->Sem());
    builder.symbols_ = program->Symbols();
    builder.diagnostics_ = program->Diagnostics();
    return builder;
}

bool ProgramBuilder::IsValid() const {
    return !diagnostics_.contains_errors();
}

void ProgramBuilder::MarkAsMoved() {
    AssertNotMoved();
    moved_ = true;
}

void ProgramBuilder::AssertNotMoved() const {
    if (TINT_UNLIKELY(moved_)) {
        TINT_ICE(ProgramBuilder, const_cast<ProgramBuilder*>(this)->diagnostics_)
            << "Attempting to use ProgramBuilder after it has been moved";
    }
}

const type::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const {
    return tint::Switch(
        Sem().Get(expr),  //
        [](const sem::ValueExpression* e) { return e->Type(); },
        [](const sem::TypeExpression* e) { return e->Type(); });
}

const type::Type* ProgramBuilder::TypeOf(const ast::Variable* var) const {
    auto* sem = Sem().Get(var);
    return sem ? sem->Type() : nullptr;
}

const type::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const {
    return Sem().Get(type_decl);
}

std::string ProgramBuilder::FriendlyName(ast::Type type) const {
    TINT_ASSERT_PROGRAM_IDS_EQUAL(ProgramBuilder, type, ID());
    return type.expr ? Symbols().NameFor(type->identifier->symbol) : "<null>";
}

std::string ProgramBuilder::FriendlyName(const type::Type* type) const {
    return type ? type->FriendlyName(Symbols()) : "<null>";
}

std::string ProgramBuilder::FriendlyName(std::nullptr_t) const {
    return "<null>";
}

ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}

const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Expression* expr) {
    // Create a temporary variable of inferred type from expr.
    return Decl(Let(symbols_.New(), expr));
}

const ast::VariableDeclStatement* ProgramBuilder::WrapInStatement(const ast::Variable* v) {
    return create<ast::VariableDeclStatement>(v);
}

const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Statement* stmt) {
    return stmt;
}

const ast::Function* ProgramBuilder::WrapInFunction(utils::VectorRef<const ast::Statement*> stmts) {
    return Func("test_function", {}, ty.void_(), std::move(stmts),
                utils::Vector{
                    create<ast::StageAttribute>(ast::PipelineStage::kCompute),
                    WorkgroupSize(1_i, 1_i, 1_i),
                });
}

const constant::Value* ProgramBuilder::createSplatOrComposite(
    const type::Type* type,
    utils::VectorRef<const constant::Value*> elements) {
    if (elements.IsEmpty()) {
        return nullptr;
    }

    bool any_zero = false;
    bool all_zero = true;
    bool all_equal = true;
    auto* first = elements.Front();
    for (auto* el : elements) {
        if (!el) {
            return nullptr;
        }
        if (!any_zero && el->AnyZero()) {
            any_zero = true;
        }
        if (all_zero && !el->AllZero()) {
            all_zero = false;
        }
        if (all_equal && el != first) {
            if (!el->Equal(first)) {
                all_equal = false;
            }
        }
    }
    if (all_equal) {
        return create<constant::Splat>(type, elements[0], elements.Length());
    }

    return constant_nodes_.Create<constant::Composite>(type, std::move(elements), all_zero,
                                                       any_zero);
}

}  // namespace tint
