#include "createMetadataCmd.h"
#include "metadataPluginStrings.h"
#include <maya/MObject.h>
#include <maya/MSyntax.h>
#include <maya/MString.h>
#include <maya/MStringResource.h>
#include <maya/MFnMesh.h>
#include <maya/MFileObject.h>
#include <maya/MSelectionList.h>
#include <maya/adskDataStream.h>
#include <maya/adskDataChannel.h>
#include <maya/adskDataAssociations.h>
#include <float.h>
#include <string>
#define F_RAND float((4000000.0 * ((float)rand()/(float)RAND_MAX)) - 2000000.0)
#define D_RAND ((4000000000.0 * ((double)rand()/(double)RAND_MAX)) - 2000000000.0)
static const char* flagChannelName      ( "-cn" );
static const char* flagChannelNameLong  ( "-channelName" );
static const char* flagStreamName       ( "-sn" );
static const char* flagStreamNameLong   ( "-streamName" );
static const char* flagStructure        ( "-s" );
static const char* flagStructureLong    ( "-structure" );
MSyntax createMetadataCmd::cmdSyntax()
 
{
    
    
    
    srand( 123 );
    return syntax;
}
void* createMetadataCmd::creator()
{
    return new createMetadataCmd;
}
const char* createMetadataCmd::name()
{
    return "createMetadata";
}
createMetadataCmd::createMetadataCmd()
: fNodes()
, fDGModifier()
, fIndexList()
, fChannelName()
, fStreamName()
{
}
createMetadataCmd::~createMetadataCmd()
{
}
bool
createMetadataCmd::isUndoable() const
{
    return true;
}
{
    
    
    
    fStructureFlag.parse(argsDb, flagStructure);
    if( fStructureFlag.isSet() )
    {
        if( ! fStructureFlag.isArgValid() )
        {
            displayError( errMsg );
        }
        MString structureName( fStructureFlag.arg() );
 
        if( ! fStructure )
        {
            msg.
format( fmt, structureName );
            displayError(msg);
        }
    }
    else
    {
        displayError( err );
    }
    
    
    
    fStreamNameFlag.parse(argsDb, flagStreamName);
    if( fStreamNameFlag.isSet() )
    {
        if( ! fStreamNameFlag.isArgValid() )
        {
            displayError( errMsg );
        }
        fStreamName = fStreamNameFlag.arg();
    }
    else
    {
        displayError( err );
    }
    
    
    
    fChannelNameFlag.parse(argsDb, flagChannelName);
    if( fChannelNameFlag.isSet() )
    {
        if( ! fChannelNameFlag.isArgValid() )
        {
            displayError( errMsg );
        }
        fChannelName = fChannelNameFlag.arg().asChar();
    }
    else
    {
        displayError( err );
    }
    
    
    
    
    
    
    
    
    fNodes.clear();
    MStatError(status, "argsDb.getObjects()");
    for (
unsigned int i = 0; i<objects.
length(); ++i)
 
    {
        MStatError(status, "objects.getDependNode()");  
        fNodes.append( node );
    }
    if( fNodes.length() == 0 )
    {
        displayError(msg);
    }
    return status;
}
{
    status = checkArgs(argsDb);
    {
        return status;
    }
    clearResult();
    for( unsigned int i=0; i<fNodes.length(); ++i )
    {
        
        
        if( oldStream )
        {
            msg.
format( fmt, fStreamName );
            displayError( msg );
            continue;
        }
        unsigned int indexCount = 0;
        
        {
            MFnMesh mesh( fNodes[i], &status );
 
            
            if( fChannelName == "face" )
            {
                indexCount = mesh.numPolygons();
            }
            else if( fChannelName == "edge" )
            {
                indexCount = mesh.numEdges();
            }
            else if( fChannelName == "vertex" )
            {
                indexCount = mesh.numVertices();
            }
            else if( fChannelName == "vertexFace" )
            {
                indexCount = mesh.numFaceVertices();
            }
            else
            {
                indexCount = rand() % 100 + 1;
            }
        }
        else
        {
            
            indexCount = rand() % 100 + 1;
        }
        
        unsigned int structureMemberCount = fStructure->memberCount();
        for( unsigned int m=0; m<indexCount; ++m )
        {
            
            
            for( unsigned int i=0; i<structureMemberCount; ++i )
            {
                handle.setPositionByMemberIndex( i );
                for( unsigned int d=0; d<handle.dataLength(); ++d )
                {
                    switch( handle.dataType() )
                    {
                        case adsk::Data::Member::kBoolean:
                        {
                            bool* data = handle.asBoolean();
                            data[d] = (rand() % 2 == 1);
                            break;
                        }
                        case adsk::Data::Member::kDouble:
                        {
                            double* data = handle.asDouble();
                            data[d] = D_RAND;
                            break;
                        }
                        case adsk::Data::Member::kDoubleMatrix4x4:
                        {
                            double* data = handle.asDoubleMatrix4x4();
                            data[d*16+0] = D_RAND;
                            data[d*16+1] = D_RAND;
                            data[d*16+2] = D_RAND;
                            data[d*16+3] = D_RAND;
                            data[d*16+4] = D_RAND;
                            data[d*16+5] = D_RAND;
                            data[d*16+6] = D_RAND;
                            data[d*16+7] = D_RAND;
                            data[d*16+8] = D_RAND;
                            data[d*16+9] = D_RAND;
                            data[d*16+10] = D_RAND;
                            data[d*16+11] = D_RAND;
                            data[d*16+12] = D_RAND;
                            data[d*16+13] = D_RAND;
                            data[d*16+14] = D_RAND;
                            data[d*16+15] = D_RAND;
                            break;
                        }
                        case adsk::Data::Member::kFloat:
                        {
                            float* data = handle.asFloat();
                            data[d] = F_RAND;
                            break;
                        }
                        case adsk::Data::Member::kFloatMatrix4x4:
                        {
                            float* data = handle.asFloatMatrix4x4();
                            data[d*16+0] = F_RAND;
                            data[d*16+1] = F_RAND;
                            data[d*16+2] = F_RAND;
                            data[d*16+3] = F_RAND;
                            data[d*16+4] = F_RAND;
                            data[d*16+5] = F_RAND;
                            data[d*16+6] = F_RAND;
                            data[d*16+7] = F_RAND;
                            data[d*16+8] = F_RAND;
                            data[d*16+9] = F_RAND;
                            data[d*16+10] = F_RAND;
                            data[d*16+11] = F_RAND;
                            data[d*16+12] = F_RAND;
                            data[d*16+13] = F_RAND;
                            data[d*16+14] = F_RAND;
                            data[d*16+15] = F_RAND;
                            break;
                        }
                        case adsk::Data::Member::kInt8:
                        {
                            signed char* data = handle.asInt8();
                            data[d] = rand() % 255 - 127;
                            break;
                        }
                        case adsk::Data::Member::kInt16:
                        {
                            short* data = handle.asInt16();
                            data[d] = rand() % 65535 - 32767;
                            break;
                        }
                        case adsk::Data::Member::kInt32:
                        {
                            int* data = handle.asInt32();
                            data[d] = (rand()/2) * (rand() % 2 == 1 ? 1 : -1);
                            break;
                        }
                        case adsk::Data::Member::kInt64:
                        {
                            int64_t* data = handle.asInt64();
                            data[d] = rand() * 10 * (rand() % 2 == 1 ? 1 : -1);
                            break;
                        }
                        case adsk::Data::Member::kUInt8:
                        {
                            unsigned char* data = handle.asUInt8();
                            data[d] = rand() % 255;
                            break;
                        }
                        case adsk::Data::Member::kUInt16:
                        {
                            unsigned short* data = handle.asUInt16();
                            data[d] = rand() % 65535;
                            break;
                        }
                        case adsk::Data::Member::kUInt32:
                        {
                            unsigned int* data = handle.asUInt32();
                            data[d] = rand();
                            break;
                        }
                        case adsk::Data::Member::kUInt64:
                        {
                            uint64_t* data = handle.asUInt64();
                            data[d] = rand() * 10;
                            break;
                        }
                        case adsk::Data::Member::kString:
                        {
                            char** data = handle.asString();
                            data[d] = (char*) malloc( sizeof(char) * 9);
                            for( unsigned int s=0; s<8; ++s )
                            {
                                data[d][s] = rand() % 26 + 'a';
                            }
                            data[d][8] = '\0';
                            break;
                        }
                        default:
                        {
                            
                            assert( false );
                            break;
                        }
                    }
                }
            }
            newStream.setElement( m, handle );
        }
        newChannel.setDataStream( newStream );
        newMetadata.setChannel( newChannel );
        fDGModifier.setMetadata( fNodes[i], newMetadata );
        status = fDGModifier.doIt();
        {
            
            
            
            
            theResult.
append( (
int) fNodes.length() );
            theResult.
append( (
int) indexCount );
            theResult.
append( (
int) structureMemberCount );
            setResult( theResult );
        }
        else
        {
            msg.
format( fmt, node.name() );
            displayError( msg );
        }
    }
    return status;
}
MStatus createMetadataCmd::redoIt()
 
{
    return fDGModifier.doIt();
}
MStatus createMetadataCmd::undoIt()
 
{
    return fDGModifier.undoIt();
}