// 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.

#ifndef SRC_TINT_IR_BLOCK_H_
#define SRC_TINT_IR_BLOCK_H_

#include <utility>

#include "src/tint/ir/block_param.h"
#include "src/tint/ir/branch.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/utils/vector.h"

namespace tint::ir {

/// A block of statements. The instructions in the block are a linear list of instructions to
/// execute. The block will branch at the end. The only blocks which do not branch are the end
/// blocks of functions.
class Block : public utils::Castable<Block> {
  public:
    /// Constructor
    Block();
    ~Block() override;

    /// @returns true if this is block has a branch target set
    bool HasBranchTarget() const {
        return instructions_.last != nullptr && instructions_.last->Is<ir::Branch>();
    }

    /// @return the node this block branches to or nullptr if the block doesn't branch
    const ir::Branch* Branch() const {
        if (!HasBranchTarget()) {
            return nullptr;
        }
        return instructions_.last->As<ir::Branch>();
    }

    /// Sets the instructions in the block
    /// @param instructions the instructions to set
    void SetInstructions(utils::VectorRef<Instruction*> instructions);

    /// @returns the instructions in the block
    Instruction* Instructions() const { return instructions_.first; }

    /// Iterator for the instructions inside a block
    class Iterator {
      public:
        /// Constructor
        /// @param inst the instruction to start iterating from
        explicit Iterator(Instruction* inst) : inst_(inst) {}
        ~Iterator() = default;

        /// Dereference operator
        /// @returns the instruction for this iterator
        Instruction* operator*() const { return inst_; }

        /// Comparison operator
        /// @param itr to compare against
        /// @returns true if this iterator and @p itr point to the same instruction
        bool operator==(const Iterator& itr) const { return itr.inst_ == inst_; }

        /// Not equal operator
        /// @param itr to compare against
        /// @returns true if this iterator and @p itr point to different instructions
        bool operator!=(const Iterator& itr) const { return !(*this == itr); }

        /// Increment operator
        /// @returns this iterator advanced to the next element
        Iterator& operator++() {
            inst_ = inst_->next;
            return *this;
        }

      private:
        Instruction* inst_ = nullptr;
    };

    /// @returns the iterator pointing to the start of the instruction list
    Iterator begin() const { return Iterator{instructions_.first}; }

    /// @returns the ending iterator
    Iterator end() const { return Iterator{nullptr}; }

    /// Adds the instruction to the beginning of the block
    /// @param inst the instruction to add
    void Prepend(Instruction* inst);
    /// Adds the instruction to the end of the block
    /// @param inst the instruction to add
    void Append(Instruction* inst);
    /// Adds the new instruction before the given instruction
    /// @param before the instruction to insert before
    /// @param inst the instruction to insert
    void InsertBefore(Instruction* before, Instruction* inst);
    /// Adds the new instruction after the given instruction
    /// @param after the instruction to insert after
    /// @param inst the instruction to insert
    void InsertAfter(Instruction* after, Instruction* inst);
    /// Replaces the target instruction with the new instruction
    /// @param target the instruction to replace
    /// @param inst the instruction to insert
    void Replace(Instruction* target, Instruction* inst);
    /// Removes the target instruction
    /// @param inst the instruction to remove
    void Remove(Instruction* inst);

    /// @returns true if the block contains no instructions
    bool IsEmpty() const { return Length() == 0; }

    /// @returns the number of instructions in the block
    size_t Length() const { return instructions_.count; }

    /// Sets the params to the block
    /// @param params the params for the block
    void SetParams(utils::VectorRef<const BlockParam*> params) { params_ = std::move(params); }
    /// @return the parameters passed into the block
    utils::VectorRef<const BlockParam*> Params() const { return params_; }
    /// @returns the params to the block
    utils::Vector<const BlockParam*, 0>& Params() { return params_; }

    /// @returns the inbound branch list for the block
    utils::VectorRef<ir::Branch*> InboundBranches() const { return inbound_branches_; }

    /// Adds the given node to the inbound branches
    /// @param node the node to add
    void AddInboundBranch(ir::Branch* node) { inbound_branches_.Push(node); }

  private:
    struct {
        Instruction* first = nullptr;
        Instruction* last = nullptr;
        size_t count = 0;
    } instructions_;

    utils::Vector<const BlockParam*, 0> params_;

    /// The list of branches into this node. This list maybe empty for several
    /// reasons:
    ///   - Node is a start node
    ///   - Node is a merge target outside control flow (e.g. an if that returns in both branches)
    ///   - Node is a continue target outside control flow (e.g. a loop that returns)
    utils::Vector<ir::Branch*, 2> inbound_branches_;
};

}  // namespace tint::ir

#endif  // SRC_TINT_IR_BLOCK_H_
