/*
 * 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 "SkSLModifiers.h"
#include "SkSLSymbol.h"
#include "../SkSLPosition.h"
#include "../SkSLUtil.h"
#include "../spirv.h"
#include <vector>
#include <memory>

namespace SkSL {

class Context;

/**
 * Represents a type, such as int or vec4.
 */
class Type : public Symbol {
public:
    struct Field {
        Field(Modifiers modifiers, SkString name, const Type* type)
        : fModifiers(modifiers)
        , fName(std::move(name))
        , fType(std::move(type)) {}

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

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

    enum Kind {
        kScalar_Kind,
        kVector_Kind,
        kMatrix_Kind,
        kArray_Kind,
        kStruct_Kind,
        kGeneric_Kind,
        kSampler_Kind,
        kOther_Kind
    };

    // Create an "other" (special) type with the given name. These types cannot be directly 
    // referenced from user code.
    Type(SkString name)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kOther_Kind) {}

    // Create a generic type which maps to the listed types. As currently implemented, there are 
    // always exactly four coercion targets, mapping to the scalar, vec2, vec3, and vec4 versions of 
    // a type.
    Type(SkString name, std::vector<const Type*> types)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kGeneric_Kind)
    , fCoercibleTypes(std::move(types)) {
        ASSERT(fCoercibleTypes.size() == 4);
    }

    // Create a struct type with the given fields.
    Type(SkString name, std::vector<Field> fields)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kStruct_Kind)
    , fFields(std::move(fields)) {}

    // Create a scalar type.
    Type(SkString name, bool isNumber)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kScalar_Kind)
    , fIsNumber(isNumber)
    , fColumns(1)
    , fRows(1) {}

    // Create a scalar type which can be coerced to the listed types.
    Type(SkString name, bool isNumber, std::vector<const Type*> coercibleTypes)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kScalar_Kind)
    , fIsNumber(isNumber)
    , fCoercibleTypes(std::move(coercibleTypes))
    , fColumns(1)
    , fRows(1) {}

    // Create a vector type.
    Type(SkString name, const Type& componentType, int columns)
    : Type(name, kVector_Kind, componentType, columns) {}

    // Create a vector or array type.
    Type(SkString name, Kind kind, const Type& componentType, int columns)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kind)
    , fComponentType(&componentType)
    , fColumns(columns)
    , fRows(1)    
    , fDimensions(SpvDim1D) {}

    // Create a matrix type.
    Type(SkString name, const Type& componentType, int columns, int rows)
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kMatrix_Kind)
    , fComponentType(&componentType)
    , fColumns(columns)
    , fRows(rows)    
    , fDimensions(SpvDim1D) {}

    // Create a sampler type.
    Type(SkString name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, 
         bool isSampled) 
    : INHERITED(Position(), kType_Kind, std::move(name))
    , fTypeKind(kSampler_Kind)
    , fDimensions(dimensions)
    , fIsDepth(isDepth)
    , fIsArrayed(isArrayed)
    , fIsMultisampled(isMultisampled)
    , fIsSampled(isSampled) {}

    SkString name() const {
        return fName;
    }

    SkString description() const override {
        return fName;
    }

    bool operator==(const Type& other) const {
        return fName == other.fName;
    }

    bool operator!=(const Type& other) const {
        return fName != other.fName;
    }

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

    /**
     * Returns true if this is a numeric scalar type.
     */
    bool isNumber() const {
        return fIsNumber;
    }

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

    /**
     * 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 true if a conversion is possible, false otherwise. The value of the out 
     * parameter is undefined if false is returned.
     */
    bool determineCoercionCost(const Type& other, int* outCost) const;

    /**
     * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
     * type of kFloat_Type). For all other types, causes an assertion failure.
     */
    const Type& componentType() const {
        ASSERT(fComponentType);
        return *fComponentType;
    }

    /**
     * For matrices and vectors, returns the number of columns (e.g. both mat3 and vec3 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 assertion failure.
     */
    int columns() const {
        ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || 
               fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
        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 assertion failure.
     */
    int rows() const {
        ASSERT(fRows > 0);
        return fRows;
    }

    const std::vector<Field>& fields() const {
        ASSERT(fTypeKind == kStruct_Kind);
        return fFields;
    }

    /**
     * For generic types, returns the types that this generic type can substitute for. For other
     * types, returns a list of other types that this type can be coerced into.
     */
    const std::vector<const Type*>& coercibleTypes() const {
        ASSERT(fCoercibleTypes.size() > 0);
        return fCoercibleTypes;
    }

    int dimensions() const {
        ASSERT(fTypeKind == kSampler_Kind);
        return fDimensions;
    }

    bool isDepth() const {
        ASSERT(fTypeKind == kSampler_Kind);
        return fIsDepth;
    }

    bool isArrayed() const {
        ASSERT(fTypeKind == kSampler_Kind);
        return fIsArrayed;
    }

    bool isMultisampled() const {
        ASSERT(fTypeKind == kSampler_Kind);
        return fIsMultisampled;
    }

    bool isSampled() const {
        ASSERT(fTypeKind == kSampler_Kind);
        return fIsSampled;
    }

    static size_t vector_alignment(size_t componentSize, int columns) {
        return componentSize * (columns + columns % 2);
    }

    /**
     * Returns the type's required alignment (when putting this type into a struct, the offset must
     * be a multiple of the alignment).
     */
    size_t alignment() const {
        // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout
        switch (fTypeKind) {
            case kScalar_Kind:
                return this->size();
            case kVector_Kind:
                return vector_alignment(fComponentType->size(), fColumns);
            case kMatrix_Kind:
                return (vector_alignment(fComponentType->size(), fRows) + 15) & ~15;
            case kArray_Kind:
                // round up to next multiple of 16
                return (fComponentType->alignment() + 15) & ~15;
            case kStruct_Kind: {
                size_t result = 16;
                for (size_t i = 0; i < fFields.size(); i++) {
                    size_t alignment = fFields[i].fType->alignment();
                    if (alignment > result) {
                        result = alignment;
                    }
                }
            }
            default:
                ABORT(("cannot determine size of type " + fName).c_str());
        }
    }

    /**
     * For matrices and arrays, returns the number of bytes from the start of one entry (row, in
     * the case of matrices) to the start of the next.
     */
    size_t stride() const {
        switch (fTypeKind) {
            case kMatrix_Kind: // fall through
            case kArray_Kind:
                return this->alignment();
            default:
                ABORT("type does not have a stride");
        }
    }

    /**
     * Returns the size of this type in bytes.
     */
    size_t size() const {
        switch (fTypeKind) {
            case kScalar_Kind:
                // FIXME need to take precision into account, once we figure out how we want to
                // handle it...
                return 4;
            case kVector_Kind:
                return fColumns * fComponentType->size();
            case kMatrix_Kind:
                return vector_alignment(fComponentType->size(), fRows) * fColumns;
            case kArray_Kind:
                return fColumns * this->stride();
            case kStruct_Kind: {
                size_t total = 0;
                for (size_t i = 0; i < fFields.size(); i++) {
                    size_t alignment = fFields[i].fType->alignment();
                    if (total % alignment != 0) {
                        total += alignment - total % alignment;
                    }
                    ASSERT(false);
                    ASSERT(total % alignment == 0);
                    total += fFields[i].fType->size();
                }
                return total;
            }
            default:
                ABORT(("cannot determine size of type " + fName).c_str());
        }
    }

    /**
     * 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;

private:
    typedef Symbol INHERITED;

    const Kind fTypeKind;
    const bool fIsNumber = false;
    const Type* fComponentType = nullptr;
    const std::vector<const Type*> fCoercibleTypes;
    const int fColumns = -1;
    const int fRows = -1;
    const std::vector<Field> fFields;
    const SpvDim_ fDimensions = SpvDim1D;
    const bool fIsDepth = false;
    const bool fIsArrayed = false;
    const bool fIsMultisampled = false;
    const bool fIsSampled = false;
};

} // namespace

#endif
