//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/translator/ParseContext.h"

//
// Use this class to carry along data from node to node in 
// the traversal
//
class TConstTraverser : public TIntermTraverser {
public:
    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t)
        : error(false),
          index(0),
          unionArray(cUnion),
          type(t),
          constructorType(constructType),
          singleConstantParam(singleConstParam),
          infoSink(sink),
          size(0),
          isDiagonalMatrixInit(false),
          matrixCols(0),
          matrixRows(0) {
    }

    bool error;

protected:
    void visitSymbol(TIntermSymbol*);
    void visitConstantUnion(TIntermConstantUnion*);
    bool visitBinary(Visit visit, TIntermBinary*);
    bool visitUnary(Visit visit, TIntermUnary*);
    bool visitSelection(Visit visit, TIntermSelection*);
    bool visitAggregate(Visit visit, TIntermAggregate*);
    bool visitLoop(Visit visit, TIntermLoop*);
    bool visitBranch(Visit visit, TIntermBranch*);

    size_t index;
    ConstantUnion *unionArray;
    TType type;
    TOperator constructorType;
    bool singleConstantParam;
    TInfoSink& infoSink;
    size_t size; // size of the constructor ( 4 for vec4)
    bool isDiagonalMatrixInit;
    int matrixCols; // columns of the matrix
    int matrixRows; // rows of the matrix
};

//
// The rest of the file are the traversal functions.  The last one
// is the one that starts the traversal.
//
// Return true from interior nodes to have the external traversal
// continue on to children.  If you process children yourself,
// return false.
//

void TConstTraverser::visitSymbol(TIntermSymbol* node)
{
    infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
    return;

}

bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
{
    TQualifier qualifier = node->getType().getQualifier();
    
    if (qualifier != EvqConst) {
        TString buf;
        buf.append("'constructor' : assigning non-constant to ");
        buf.append(type.getCompleteString());
        infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
        error = true;
        return false;  
    }

   infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
    
    return false;
}

bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
{
    TString buf;
    buf.append("'constructor' : assigning non-constant to ");
    buf.append(type.getCompleteString());
    infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
    error = true;
    return false;  
}

bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
{
    if (!node->isConstructor() && node->getOp() != EOpComma) {
        TString buf;
        buf.append("'constructor' : assigning non-constant to ");
        buf.append(type.getCompleteString());
        infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
        error = true;
        return false;  
    }

    if (node->getSequence().size() == 0) {
        error = true;
        return false;
    }

    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
    if (flag) 
    {
        singleConstantParam = true; 
        constructorType = node->getOp();
        size = node->getType().getObjectSize();

        if (node->getType().isMatrix()) {
            isDiagonalMatrixInit = true;
            matrixCols = node->getType().getCols();
            matrixRows = node->getType().getRows();
        }
    }       

    for (TIntermSequence::iterator p = node->getSequence().begin(); 
                                   p != node->getSequence().end(); p++) {

        if (node->getOp() == EOpComma)
            index = 0;           

        (*p)->traverse(this);
    }   
    if (flag) 
    {
        singleConstantParam = false;   
        constructorType = EOpNull;
        size = 0;
        isDiagonalMatrixInit = false;
        matrixCols = 0;
        matrixRows = 0;
    }
    return false;
}

bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
{
    infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
    error = true;
    return false;
}

void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
{
    if (!node->getUnionArrayPointer())
    {
        // The constant was not initialized, this should already have been logged
        assert(infoSink.info.size() != 0);
        return;
    }

    ConstantUnion* leftUnionArray = unionArray;
    size_t instanceSize = type.getObjectSize();
    TBasicType basicType = type.getBasicType();

    if (index >= instanceSize)
        return;

    if (!singleConstantParam) {
        size_t objectSize = node->getType().getObjectSize();
    
        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        for (size_t i=0; i < objectSize; i++) {
            if (index >= instanceSize)
                return;
            leftUnionArray[index].cast(basicType, rightUnionArray[i]);

            (index)++;
        }
    } else {
        size_t totalSize = index + size;
        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        if (!isDiagonalMatrixInit) {
            int count = 0;
            for (size_t i = index; i < totalSize; i++) {
                if (i >= instanceSize)
                    return;

                leftUnionArray[i].cast(basicType, rightUnionArray[count]);

                (index)++;
                
                if (node->getType().getObjectSize() > 1)
                    count++;
            }
        }
        else
        {
            // for matrix diagonal constructors from a single scalar
            for (int i = 0, col = 0; col < matrixCols; col++)
            {
                for (int row = 0; row < matrixRows; row++, i++)
                {
                    if (col == row)
                    {
                        leftUnionArray[i].cast(basicType, rightUnionArray[0]);
                    }
                    else
                    {
                        leftUnionArray[i].setFConst(0.0f);
                    }

                    (index)++;
                }
            }
        }
    }
}

bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
{
    infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
    error = true;
    return false;
}

bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
{
    infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
    error = true;
    return false;
}

//
// This function is the one to call externally to start the traversal.
// Individual functions can be initialized to 0 to skip processing of that
// type of node.  It's children will still be processed.
//
bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
{
    if (root == 0)
        return false;

    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);

    root->traverse(&it);
    if (it.error)
        return true;
    else
        return false;
}
