// 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_FUNCTION_H_
#define SRC_TINT_IR_FUNCTION_H_

#include <array>
#include <optional>
#include <utility>

#include "src/tint/ir/function_param.h"
#include "src/tint/ir/value.h"
#include "src/tint/symbol.h"
#include "src/tint/type/type.h"

// Forward declarations
namespace tint::ir {
class Block;
class FunctionTerminator;
}  // namespace tint::ir

namespace tint::ir {

/// An IR representation of a function
class Function : public utils::Castable<Function, Value> {
  public:
    /// The pipeline stage for an entry point
    enum class PipelineStage {
        /// Not a pipeline entry point
        kUndefined,
        /// Vertex
        kCompute,
        /// Fragment
        kFragment,
        /// Vertex
        kVertex,
    };

    /// Attributes attached to return types
    enum class ReturnAttribute {
        /// No return attribute
        kNone,
        /// Location attribute
        kLocation,
        /// Builtin Position attribute
        kPosition,
        /// Builtin FragDepth attribute
        kFragDepth,
        /// Builtin SampleMask
        kSampleMask,
        /// Invariant attribute
        kInvariant,
    };

    /// Constructor
    /// @param n the function name
    /// @param rt the function return type
    /// @param stage the function stage
    /// @param wg_size the workgroup_size
    Function(Symbol n,
             const type::Type* rt,
             PipelineStage stage = PipelineStage::kUndefined,
             std::optional<std::array<uint32_t, 3>> wg_size = {});
    ~Function() override;

    /// @returns the function name
    Symbol Name() const { return name_; }

    /// Sets the function stage
    /// @param stage the stage to set
    void SetStage(PipelineStage stage) { pipeline_stage_ = stage; }

    /// @returns the function pipeline stage
    PipelineStage Stage() const { return pipeline_stage_; }

    /// Sets the workgroup size
    /// @param x the x size
    /// @param y the y size
    /// @param z the z size
    void SetWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) { workgroup_size_ = {x, y, z}; }

    /// @returns the workgroup size information
    std::optional<std::array<uint32_t, 3>> WorkgroupSize() const { return workgroup_size_; }

    /// @returns the return type for the function
    const type::Type* ReturnType() const { return return_type_; }

    /// Sets the return attributes
    /// @param attrs the attributes to set
    void SetReturnAttributes(utils::VectorRef<ReturnAttribute> attrs) {
        return_attributes_ = std::move(attrs);
    }
    /// @returns the return attributes
    utils::VectorRef<ReturnAttribute> ReturnAttributes() const { return return_attributes_; }

    /// Sets the return location
    /// @param loc the location to set
    void SetReturnLocation(std::optional<uint32_t> loc) { return_location_ = loc; }
    /// @returns the return location
    std::optional<uint32_t> ReturnLocation() const { return return_location_; }

    /// Sets the function parameters
    /// @param params the function paramters
    void SetParams(utils::VectorRef<FunctionParam*> params) { params_ = std::move(params); }

    /// @returns the function parameters
    utils::VectorRef<FunctionParam*> Params() const { return params_; }

    /// Sets the start target for the function
    /// @param target the start target
    void SetStartTarget(Block* target) { start_target_ = target; }
    /// @returns the function start target
    Block* StartTarget() const { return start_target_; }

    /// Sets the end target for the function
    /// @param target the end target
    void SetEndTarget(FunctionTerminator* target) { end_target_ = target; }
    /// @returns the function end target
    FunctionTerminator* EndTarget() const { return end_target_; }

  private:
    Symbol name_;
    const type::Type* return_type_;
    PipelineStage pipeline_stage_;
    std::optional<std::array<uint32_t, 3>> workgroup_size_;

    utils::Vector<ReturnAttribute, 1> return_attributes_;
    std::optional<uint32_t> return_location_;

    utils::Vector<FunctionParam*, 1> params_;

    Block* start_target_ = nullptr;
    FunctionTerminator* end_target_ = nullptr;
};

utils::StringStream& operator<<(utils::StringStream& out, Function::PipelineStage value);
utils::StringStream& operator<<(utils::StringStream& out, Function::ReturnAttribute value);

}  // namespace tint::ir

#endif  // SRC_TINT_IR_FUNCTION_H_
