/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKIASL_TYPE
#define SKIASL_TYPE

#include "src/sksl/SkSLPosition.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLModifiers.h"
#include "src/sksl/ir/SkSLSymbol.h"
#include "src/sksl/spirv.h"
#include <algorithm>
#include <climits>
#include <vector>
#include <memory>

namespace SkSL {

class BuiltinTypes;
class Context;

struct CoercionCost {
    static CoercionCost Free()              { return {    0,    0, false }; }
    static CoercionCost Normal(int cost)    { return { cost,    0, false }; }
    static CoercionCost Narrowing(int cost) { return {    0, cost, false }; }
    static CoercionCost Impossible()        { return {    0,    0,  true }; }

    bool isPossible(bool allowNarrowing) const {
        return !fImpossible && (fNarrowingCost == 0 || allowNarrowing);
    }

    // Addition of two costs. Saturates at Impossible().
    CoercionCost operator+(CoercionCost rhs) const {
        if (fImpossible || rhs.fImpossible) {
            return Impossible();
        }
        return { fNormalCost + rhs.fNormalCost, fNarrowingCost + rhs.fNarrowingCost, false };
    }

    bool operator<(CoercionCost rhs) const {
        return std::tie(    fImpossible,     fNarrowingCost,     fNormalCost) <
               std::tie(rhs.fImpossible, rhs.fNarrowingCost, rhs.fNormalCost);
    }

    int  fNormalCost;
    int  fNarrowingCost;
    bool fImpossible;
};

/**
 * Represents a type, such as int or float4.
 */
class Type final : public Symbol {
public:
    static constexpr Kind kSymbolKind = Kind::kType;

    struct Field {
        Field(Modifiers modifiers, StringFragment name, const Type* type)
        : fModifiers(modifiers)
        , fName(name)
        , fType(std::move(type)) {}

        String description() const {
            return fType->displayName() + " " + fName + ";";
        }

        Modifiers fModifiers;
        StringFragment fName;
        const Type* fType;
    };

    enum class TypeKind {
        kArray,
        kEnum,
        kGeneric,
        kMatrix,
        kOther,
        kSampler,
        kSeparateSampler,
        kScalar,
        kStruct,
        kTexture,
        kVector
    };

    enum class NumberKind {
        kFloat,
        kSigned,
        kUnsigned,
        kBoolean,
        kNonnumeric
    };

    Type(const Type& other) = delete;

    /** Creates an enum type. */
    static std::unique_ptr<Type> MakeEnumType(String name) {
        return std::unique_ptr<Type>(new Type(std::move(name), TypeKind::kEnum));
    }

    /** Creates a struct type with the given fields. */
    static std::unique_ptr<Type> MakeStructType(int offset, String name,
                                                std::vector<Field> fields) {
        return std::unique_ptr<Type>(new Type(offset, std::move(name), std::move(fields)));
    }

    /** Creates an array type. */
    static constexpr int kUnsizedArray = -1;
    static std::unique_ptr<Type> MakeArrayType(String name, const Type& componentType,
                                               int columns) {
        return std::unique_ptr<Type>(new Type(std::move(name), TypeKind::kArray, componentType,
                                              columns));
    }

    /** Creates a clone of this Type, if needed, and inserts it into a different symbol table. */
    const Type* clone(SymbolTable* symbolTable) const;

    /**
     * Returns true if this type is known to come from BuiltinTypes. If this returns true, the Type
     * will always be available in the root SymbolTable and never needs to be copied to migrate an
     * Expression from one location to another. If it returns false, the Type might not exist in a
     * separate SymbolTable and you'll need to consider copying it.
     */
    bool isInBuiltinTypes() const {
        return !(this->isArray() || this->isStruct() || this->isEnum());
    }

    String displayName() const {
        return this->scalarTypeForLiteral().name();
    }

    String description() const override {
        return this->displayName();
    }

    bool isPrivate() const {
        return this->name().startsWith("$");
    }

    bool operator==(const Type& other) const {
        return this->name() == other.name();
    }

    bool operator!=(const Type& other) const {
        return this->name() != other.name();
    }

    /**
     * Returns the category (scalar, vector, matrix, etc.) of this type.
     */
    TypeKind typeKind() const {
        return fTypeKind;
    }

    NumberKind numberKind() const {
        return fNumberKind;
    }

    /**
     * Returns true if this type is a bool.
     */
    bool isBoolean() const {
        return fNumberKind == NumberKind::kBoolean;
    }

    /**
     * Returns true if this is a numeric scalar type.
     */
    bool isNumber() const {
        return this->isFloat() || this->isInteger();
    }

    /**
     * Returns true if this is a floating-point scalar type (float or half).
     */
    bool isFloat() const {
        return fNumberKind == NumberKind::kFloat;
    }

    /**
     * Returns true if this is a signed scalar type (int or short).
     */
    bool isSigned() const {
        return fNumberKind == NumberKind::kSigned;
    }

    /**
     * Returns true if this is an unsigned scalar type (uint or ushort).
     */
    bool isUnsigned() const {
        return fNumberKind == NumberKind::kUnsigned;
    }

    /**
     * Returns true if this is a signed or unsigned integer.
     */
    bool isInteger() const {
        return this->isSigned() || this->isUnsigned();
    }

    /**
     * Returns true if this is an "opaque type" (an external object which the shader references in
     * some fashion). https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Opaque_types
     */
    bool isOpaque() const {
        switch (fTypeKind) {
            case TypeKind::kOther:
            case TypeKind::kSampler:
            case TypeKind::kSeparateSampler:
            case TypeKind::kTexture:
                return true;
            default:
                return false;
        }
    }

    /**
     * Returns the "priority" of a number type, in order of float > half > int > short.
     * When operating on two number types, the result is the higher-priority type.
     */
    int priority() const {
        return fPriority;
    }

    /**
     * Returns true if an instance of this type can be freely coerced (implicitly converted) to
     * another type.
     */
    bool canCoerceTo(const Type& other, bool allowNarrowing) const {
        return this->coercionCost(other).isPossible(allowNarrowing);
    }

    /**
     * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
     * is a number with no particular meaning other than that lower costs are preferable to higher
     * costs. Returns INT_MAX if the coercion is not possible.
     */
    CoercionCost coercionCost(const Type& other) const;

    /**
     * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
     * type of Float). For arrays, returns the base type. For all other types, returns the type
     * itself.
     */
    const Type& componentType() const {
        if (fComponentType) {
            return *fComponentType;
        }
        return *this;
    }

    /**
     * For texturesamplers, returns the type of texture it samples (e.g., sampler2D has
     * a texture type of texture2D).
     */
    const Type& textureType() const {
        SkASSERT(fTextureType);
        return *fTextureType;
    }

    /**
     * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3 return 3).
     * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
     * For all other types, causes an SkASSERTion failure.
     */
    int columns() const {
        SkASSERT(this->isScalar() || this->isVector() || this->isMatrix() || this->isArray());
        return fColumns;
    }

    /**
     * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars,
     * returns 1. For all other types, causes an SkASSERTion failure.
     */
    int rows() const {
        SkASSERT(fRows > 0);
        return fRows;
    }

    const std::vector<Field>& fields() const {
        SkASSERT(this->isStruct());
        return fFields;
    }

    /**
     * For generic types, returns the types that this generic type can substitute for.
     */
    const std::vector<const Type*>& coercibleTypes() const {
        SkASSERT(fCoercibleTypes.size() > 0);
        return fCoercibleTypes;
    }

    SpvDim_ dimensions() const {
        SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
        return fDimensions;
    }

    bool isDepth() const {
        SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
        return fIsDepth;
    }

    bool isArrayedTexture() const {
        SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
        return fIsArrayed;
    }

    bool isScalar() const {
        return fTypeKind == TypeKind::kScalar;
    }

    bool isLiteral() const {
        return fScalarTypeForLiteral != nullptr;
    }

    const Type& scalarTypeForLiteral() const {
        return fScalarTypeForLiteral ? *fScalarTypeForLiteral : *this;
    }

    bool isVector() const {
        return fTypeKind == TypeKind::kVector;
    }

    bool isMatrix() const {
        return fTypeKind == TypeKind::kMatrix;
    }

    bool isArray() const {
        return fTypeKind == TypeKind::kArray;
    }

    bool isStruct() const {
        return fTypeKind == TypeKind::kStruct;
    }

    bool isEnum() const {
        return fTypeKind == TypeKind::kEnum;
    }

    bool isMultisampled() const {
        SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
        return fIsMultisampled;
    }

    bool isSampled() const {
        SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
        return fIsSampled;
    }

    bool highPrecision() const {
        if (fComponentType) {
            return fComponentType->highPrecision();
        }
        return fHighPrecision;
    }

    bool isOrContainsArray() const;

    /**
     * Returns the corresponding vector or matrix type with the specified number of columns and
     * rows.
     */
    const Type& toCompound(const Context& context, int columns, int rows) const;

    /**
     * Coerces the passed-in expression to this type. If the types are incompatible, reports an
     * error and returns null.
     */
    std::unique_ptr<Expression> coerceExpression(std::unique_ptr<Expression> expr,
                                                 const Context& context) const;

private:
    friend class BuiltinTypes;

    using INHERITED = Symbol;

    // Constructor for MakeOtherType.
    Type(const char* name)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kOther)
            , fNumberKind(NumberKind::kNonnumeric) {}

    // Constructor for MakeEnumType and MakeSeparateSamplerType.
    Type(String name, TypeKind kind)
            : INHERITED(-1, kSymbolKind, "")
            , fNameString(std::move(name))
            , fTypeKind(kind)
            , fNumberKind(NumberKind::kNonnumeric) {
        fName = StringFragment(fNameString.c_str(), fNameString.length());
    }

    // Constructor for MakeGenericType.
    Type(const char* name, std::vector<const Type*> types)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kGeneric)
            , fNumberKind(NumberKind::kNonnumeric)
            , fCoercibleTypes(std::move(types)) {}

    // Constructor for MakeScalarType.
    Type(const char* name, NumberKind numberKind, int priority, bool highPrecision)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kScalar)
            , fNumberKind(numberKind)
            , fPriority(priority)
            , fColumns(1)
            , fRows(1)
            , fHighPrecision(highPrecision) {}

    // Constructor for MakeLiteralType.
    Type(const char* name, const Type& scalarType, int priority)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kScalar)
            , fNumberKind(scalarType.numberKind())
            , fPriority(priority)
            , fColumns(1)
            , fRows(1)
            , fHighPrecision(scalarType.highPrecision())
            , fScalarTypeForLiteral(&scalarType) {}

    // Constructor shared by MakeVectorType and MakeArrayType.
    Type(String name, TypeKind kind, const Type& componentType, int columns)
            : INHERITED(-1, kSymbolKind, "")
            , fNameString(std::move(name))
            , fTypeKind(kind)
            , fNumberKind(NumberKind::kNonnumeric)
            , fComponentType(&componentType)
            , fColumns(columns)
            , fRows(1)
            , fDimensions(SpvDim1D) {
        if (this->isArray()) {
            // Allow either explicitly-sized or unsized arrays.
            SkASSERT(this->columns() > 0 || this->columns() == kUnsizedArray);
            // Disallow multi-dimensional arrays.
            SkASSERT(!this->componentType().isArray());
        } else {
            SkASSERT(this->columns() > 0);
        }
        fName = StringFragment(fNameString.c_str(), fNameString.length());
    }

    // Constructor for MakeMatrixType.
    Type(const char* name, const Type& componentType, int columns, int rows)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kMatrix)
            , fNumberKind(NumberKind::kNonnumeric)
            , fComponentType(&componentType)
            , fColumns(columns)
            , fRows(rows)
            , fDimensions(SpvDim1D) {}

    // Constructor for MakeStructType.
    Type(int offset, String name, std::vector<Field> fields)
            : INHERITED(offset, kSymbolKind, "")
            , fNameString(std::move(name))
            , fTypeKind(TypeKind::kStruct)
            , fNumberKind(NumberKind::kNonnumeric)
            , fFields(std::move(fields)) {
        fName = StringFragment(fNameString.c_str(), fNameString.length());
    }

    // Constructor for MakeTextureType.
    Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayedTexture,
         bool isMultisampled, bool isSampled)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kTexture)
            , fNumberKind(NumberKind::kNonnumeric)
            , fDimensions(dimensions)
            , fIsDepth(isDepth)
            , fIsArrayed(isArrayedTexture)
            , fIsMultisampled(isMultisampled)
            , fIsSampled(isSampled) {}

    // Constructor for MakeSamplerType.
    Type(const char* name, const Type& textureType)
            : INHERITED(-1, kSymbolKind, name)
            , fTypeKind(TypeKind::kSampler)
            , fNumberKind(NumberKind::kNonnumeric)
            , fDimensions(textureType.dimensions())
            , fIsDepth(textureType.isDepth())
            , fIsArrayed(textureType.isArrayedTexture())
            , fIsMultisampled(textureType.isMultisampled())
            , fIsSampled(textureType.isSampled())
            , fTextureType(&textureType) {}

    String fNameString;
    TypeKind fTypeKind;
    // always kNonnumeric_NumberKind for non-scalar values
    NumberKind fNumberKind;
    int fPriority = -1;
    const Type* fComponentType = nullptr;
    std::vector<const Type*> fCoercibleTypes;
    int fColumns = -1;
    int fRows = -1;
    std::vector<Field> fFields;
    SpvDim_ fDimensions = SpvDim1D;
    bool fIsDepth = false;
    bool fIsArrayed = false;
    bool fIsMultisampled = false;
    bool fIsSampled = false;
    bool fHighPrecision = false;
    const Type* fTextureType = nullptr;
    const Type* fScalarTypeForLiteral = nullptr;
};

}  // namespace SkSL

#endif
