#ifdef WIN32
#pragma warning( disable : 4786 )
#endif
#include <maya/MIOStream.h>
#include <maya/MDagPath.h>
#include <maya/MDoubleArray.h>
#include <maya/MFloatVector.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnLightDataAttribute.h>
#include <maya/MFnMesh.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MGlobal.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MString.h>
#include "blindDataShader.h"
void mergeSort( int startIndex, int sortingOffset,
                MIntArray& sortingArray, 
int* tempSortingArray,
 
{
    if (sortingOffset == 2)
    {
        if (sortingArray[startIndex] > sortingArray[startIndex+1])
        {
            int temp = sortingArray[startIndex+1];
            sortingArray[startIndex+1] = sortingArray[startIndex];
            sortingArray[startIndex] = temp;
            double ftemp = otherArray[startIndex+1];
            otherArray[startIndex+1] = otherArray[startIndex];
            otherArray[startIndex] = ftemp;
        }
    }
    else if (sortingOffset > 2)
    {
        
        
        int leftCount = sortingOffset / 2;
        int rightCount = sortingOffset - leftCount;
        int leftIndex = startIndex;
        int rightIndex = startIndex + leftCount;
        mergeSort(leftIndex, leftCount, sortingArray, tempSortingArray,
            otherArray, tempOtherArray);
        mergeSort(rightIndex, rightCount, sortingArray, tempSortingArray,
            otherArray, tempOtherArray);
        
        
        int index = startIndex;
        while (leftIndex < (startIndex + leftCount)
            && rightIndex < (startIndex + sortingOffset) )
        {
            if (sortingArray[leftIndex] < sortingArray[rightIndex])
            {
                tempSortingArray[index] = sortingArray[leftIndex];
                tempOtherArray[index++] = otherArray[leftIndex++];
            }
            else
            {
                tempSortingArray[index] = sortingArray[rightIndex];
                tempOtherArray[index++] = otherArray[rightIndex++];
            }
        }
        
        
        while (leftIndex < (startIndex + leftCount) )
        {
            tempSortingArray[index] = sortingArray[leftIndex];
            tempOtherArray[index++] = otherArray[leftIndex++];
        }
        while (rightIndex < (startIndex + sortingOffset) )
        {
            tempSortingArray[index] = sortingArray[rightIndex];
            tempOtherArray[index++] = otherArray[rightIndex++];
        }
        
        
        for (index = startIndex; index < (startIndex + sortingOffset); ++index)
        {
            sortingArray[index] = tempSortingArray[index];
            otherArray[index] = tempOtherArray[index];
        }
    }
}
int binarySearch(
int searchValue, 
MIntArray& searchArray)
 
{
    int max = searchArray.
length();
 
    int min = 0;
    while (max - min > 1)
    {
        int currentIndex = ((max - min) / 2) + min;
        int currentValue = searchArray[currentIndex];
        if (currentValue == searchValue) return currentIndex;
        else if (currentValue < searchValue) min = currentIndex;
        else max = currentIndex;
    }
    if (searchArray[min] == searchValue) return min;
    else return -1;
}
MTypeId blindDataShader::id( 0x00086000 );
 
void* blindDataShader::creator()
{
    return new blindDataShader();
}
MStatus blindDataShader::initialize()
 
{
}
{ 
    bool k = false;
    k |= (plug==outColor);
    k |= (plug==outColorR);
    k |= (plug==outColorG);
    k |= (plug==outColorB);
    
    
    outColor = resultColor;
}
{
    glPushAttrib( GL_ALL_ATTRIB_BITS );
    glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
}
{
    glPopClientAttrib();
    glPopAttrib();
}
                                int prim,
                                unsigned int writable,
                                int indexCount,
                                const unsigned int * indexArray,
                                int vertexCount,
                                const int * vertexIDs,
                                const float * vertexArray,
                                int normalCount,
                                const float ** normalArrays,
                                int colorCount,
                                const float ** colorArrays,
                                int texCoordCount,
                                const float ** texCoordArrays,
                                const int * faceIDs,
                                const float * localUVCoord)
{
    const int blindDataUniqueID = 60;
    int i;
    
    
    
    double* colours = new double[vertexCount * 3];
    float defaultColour[3] = { 0.0f, 0.0f, 0.0f };
    MPlug plug( thisMObject(), outColor );
 
    data.getData(defaultColour[0], defaultColour[1], defaultColour[2]);
    
    
    
    
    
    bool colorFaceIds = true;
    const int *colorIDs = colorFaceIds ? faceIDs : vertexIDs;
    
    
    if (!colorFaceIds && 
        blindDataUniqueID, &stat))
    {
        MIntArray redComponentIDs, greenComponentIDs, blueComponentIDs;
 
            blindDataUniqueID, "red", redComponentIDs, redColour);
            blindDataUniqueID, "green", greenComponentIDs, greenColour);
            blindDataUniqueID, "blue", blueComponentIDs, blueColour);
        {
            
            
            
            
            
            
            
            int maxArrayLength =
            int* tempIntArray = new int[maxArrayLength];
            double* tempFloatArray = new double[maxArrayLength];
            mergeSort(0, redComponentIDs.
length(), redComponentIDs,
                tempIntArray, redColour, tempFloatArray);
            mergeSort(0, greenComponentIDs.
length(), greenComponentIDs,
                tempIntArray, greenColour, tempFloatArray);
            mergeSort(0, blueComponentIDs.
length(), blueComponentIDs,
                tempIntArray, blueColour, tempFloatArray);
            
            
            for (i = 0; i < vertexCount; ++i)
            {
                int index = binarySearch(colorIDs[i], redComponentIDs);
                if (index != -1) colours[3*i] = redColour[index];
                else colours[3*i] = defaultColour[0];
                index = binarySearch(colorIDs[i], greenComponentIDs);
                if (index != -1) colours[3*i+1] = greenColour[index];
                else colours[3*i+1] = defaultColour[1];
                index = binarySearch(colorIDs[i], blueComponentIDs);
                if (index != -1) colours[3*i+2] = blueColour[index];
                else colours[3*i+2] = defaultColour[2];
            }
        }
    }
    else
    {
        
        if (colorIDs)
        {
            int j=0;
            for (int i=0; i<vertexCount; i++)
            {
                double val = (double)colorIDs[i] / (double)vertexCount;
                colours[j++] = val;
                colours[j++] = val;
                colours[j++] = val;
            }
            
            
            
            
            
            
            const bool dumpIds = false;
            if (dumpIds)
            {
                
                const bool dumpIndexed = false;
                if (!dumpIndexed)
                {
                    for (int i=0; i<vertexCount; i++)
                    {
                        printf("Face id[%d] = %d. vertex id=%d. localUV=%g,%g\n", i, faceIDs[i], vertexIDs[i], localUVCoord[i*2],
                            localUVCoord[i * 2 + 1]);
                    }
                }
                else
                {
                    for (int i=0; i<indexCount; i++)
                    {
                        unsigned int location = indexArray[i];
                        printf("Index=%d: Face id = %d. vertex id=%d. localUV=%g,%g\n", i, faceIDs[location], vertexIDs[location],
                            localUVCoord[location * 2], localUVCoord[location * 2 + 1]);
                    }
                }
            }
        }
    }
    
    
    
    
    glPushAttrib( GL_ALL_ATTRIB_BITS );
    glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
    glDisable(GL_LIGHTING);
    glVertexPointer(3, GL_FLOAT, 0, vertexArray);
    glEnableClientState(GL_VERTEX_ARRAY);
    glColorPointer(3, GL_DOUBLE, 0, colours);
    glEnableClientState(GL_COLOR_ARRAY);
    glDrawElements(prim, indexCount, GL_UNSIGNED_INT, indexArray);
    glDisable(GL_COLOR_MATERIAL);
    glPopClientAttrib();
    glPopAttrib();
    delete[] colours;
}