#ifndef _gpuCacheCmd_h_
#define _gpuCacheCmd_h_
#include <maya/MPxCommand.h>
#include <maya/MArgDatabase.h>
#include <maya/MDagModifier.h>
#include <maya/MDagPath.h>
#include <maya/MSelectionList.h>
#include <maya/MTime.h>
#include <cassert>
#include <string>
#include <set>
#include <vector>
#include <map>
namespace GPUCache {
{
public:
    
    static void* creator();
    
    Command();
    virtual ~Command();
    virtual bool isUndoable() const;
    virtual bool hasSyntax() const;
private:
    
    enum Mode {
        kCreate = 1,
        kEdit   = 2,
        kQuery  = 4
    };
    
    
    template <class T, Mode ValidModes>
    class OptFlag
    {
    public:
        OptFlag() : fIsSet(false), fArg() {}
        unsigned int parse(
const MArgDatabase& argDb, 
const char* name)
 
        
        
        
        
        
        
        
        {
            
            return fIsSet ? 1 : 0;
        }
        bool isModeValid(const Mode currentMode)
        {
            return !fIsSet || ((currentMode & ValidModes) != 0);
        }
        
        bool isSet()        const { return fIsSet; }
        bool isArgValid()   const { return fIsArgValid; }
        const T& arg()      const { return fArg; }
        const T& arg(const T& defValue) const {
            if (isSet()) {
                assert(isArgValid());
                return fArg;
            }
            else {
                return defValue;
            }
        }
    private:
        bool        fIsSet;
        bool        fIsArgValid;
        T           fArg;
    };
    
    template <Mode ValidModes>
    class OptFlag<void, ValidModes>
    {
    public:
        OptFlag() : fIsSet(false) {}
        unsigned int parse(
const MArgDatabase& argDb, 
const char* name)
 
        
        
        
        
        
        
        
        {
            return fIsSet ? 1 : 0;
        }
        bool isModeValid(const Mode currentMode)
        {
            return !fIsSet || ((currentMode & ValidModes) != 0);
        }
        
        bool isSet()        const { return fIsSet; }
        
    private:
        bool        fIsSet;
    };
    
    class SourceAndXformNode;
    typedef std::vector<SourceAndXformNode> SourceAndXformMapping;
    
    
    void AddHierarchy(
const MDagPath&                      dagPath,
 
                      std::map<std::string, int>*          idMap,
                      std::vector<MObject>*                sourceNodes,
                      std::vector<std::vector<MDagPath> >* sourcePaths,
                      std::vector<MObject>*                gpuCacheNodes);
                     std::vector<MObject>*                sourceNodes,
                     std::vector<std::vector<MDagPath> >* sourcePaths,
                     std::vector<MObject>*                gpuCacheNodes);
    MStatus doCreate(
const std::vector<MObject>&                sourceNodes,
 
                     const std::vector<std::vector<MDagPath> >& sourcePaths,
    MStatus doQuery( 
const std::vector<MObject>& gpuCacheNodes) 
const;
 
    MStatus doEdit(  
const std::vector<MObject>& gpuCacheNodes);
 
    MStatus doBaking(
const std::vector<MObject>&                sourceNodes,
 
                     const std::vector<std::vector<MDagPath> >& sourcePaths,
                     int                         samplingRate);
    void showStats(const std::vector<MObject>& gpuCacheNodes,
    void dumpHierarchy(const std::vector<MObject>& gpuCacheNodes,
    MStatus dumpHierarchyToFile(
const std::vector<MObject>& gpuCacheNodes,
 
    void showAnimTimeRange(const std::vector<MObject>& gpuCacheNodes,
    void refresh(const std::vector<MObject>& gpuCacheNodes);
    void refreshAll();
    void refreshSettings();
    void listFileEntries();
    void listShapeEntries();
    
    
    Mode                                    fMode;
    OptFlag<MString, Mode(kCreate)>         fDirectoryFlag;
    OptFlag<MString, Mode(kCreate)>         fFileNameFlag;
    OptFlag<bool,    Mode(kCreate)>         fSaveMultipleFilesFlag;
    OptFlag<MString, Mode(kCreate)>         fFilePrefixFlag;
    OptFlag<MString, Mode(kCreate)>         fClashOptionFlag;
    OptFlag<void,    Mode(kCreate)>         fOptimizeFlag;
    OptFlag<unsigned,Mode(kCreate)>         fOptimizationThresholdFlag;
    OptFlag<MTime,   Mode(kCreate)>         fStartTimeFlag;
    OptFlag<MTime,   Mode(kCreate)>         fEndTimeFlag;
    OptFlag<MTime,   Mode(kCreate)>         fSimulationRateFlag;
    OptFlag<int,     Mode(kCreate)>         fSampleMultiplierFlag;
    OptFlag<int,     Mode(kCreate)>         fCompressLevelFlag;
    OptFlag<MString, Mode(kCreate)>         fDataFormatFlag;
    OptFlag<MString, Mode(kCreate|kQuery)>  fShowFailedFlag;
    OptFlag<void,    Mode(kQuery)>          fShowStats;
    OptFlag<void,    Mode(kQuery)>          fShowGlobalStats;
    OptFlag<MString, Mode(kQuery)>          fDumpHierarchy;
    OptFlag<void,    Mode(kQuery)>          fAnimTimeRangeFlag;
    OptFlag<void,    Mode(kQuery)>          fGpuManufacturerFlag;
    OptFlag<void,    Mode(kQuery)>          fGpuModelFlag;
    OptFlag<void,    Mode(kQuery)>          fGpuDriverVersion;
    OptFlag<void,    Mode(kQuery)>          fGpuMemorySize;
    OptFlag<void,    Mode(kCreate)>         fAllDagObjectsFlag;
    OptFlag<void,    Mode(kEdit)>           fRefreshFlag;
    OptFlag<void,    Mode(kCreate)>         fRefreshAllFlag;
    OptFlag<void,    Mode(kCreate)>         fListFileEntriesFlag;
    OptFlag<void,    Mode(kCreate)>         fListShapeEntriesFlag;
    OptFlag<void,    Mode(kEdit)>           fRefreshSettingsFlag;
    OptFlag<void,    Mode(kQuery)>          fWaitForBackgroundReadingFlag;
    OptFlag<void,    Mode(kCreate)>         fWriteMaterials;
    OptFlag<void,    Mode(kCreate)>         fUVsFlag;
    OptFlag<void,    Mode(kCreate)>         fOptimizeAnimationsForMotionBlurFlag;
    OptFlag<void,    Mode(kCreate)>         fUseBaseTessellationFlag;
    OptFlag<void,    Mode(kCreate|kEdit)>   fPromptFlag;
};
} 
#endif