#ifndef _gpuCacheShapeNode_h_
#define _gpuCacheShapeNode_h_
#include "gpuCacheGeometry.h"
#include "gpuCacheMaterial.h"
#include "CacheReader.h"
#include <maya/MObjectHandle.h>
#include <maya/MPxSurfaceShape.h>
#include <maya/MPxSurfaceShapeUI.h>
#include <maya/MMessage.h>
#include <maya/MPxGeometryData.h>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include "gpuCacheSpatialSubdivision.h"
#include <vector>
namespace GPUCache {
namespace ShapeNodePrivate {
    
    class BufferCache{
    public:
        BufferCache(double seconds){fBufferReadTime = seconds; fUseCachedBuffers = false; fTotalNumTris=0; fTotalNumVerts=0; fNumShapes=0;}
        ~BufferCache(){
        }
        std::vector<MMatrix> fXFormMatrix;
        std::vector<MMatrix> fXFormMatrixInverse;
        std::vector<IndexBuffer::ReadInterfacePtr> fTriangleVertIndices;
        std::vector<IndexBuffer::ReadInterfacePtr> fEdgeVertIndices;
        std::vector<VertexBuffer::ReadInterfacePtr> fPositions;
        std::vector<size_t> fNumTriangles;
        std::vector<size_t> fNumEdges;
        std::vector<MBoundingBox> fBoundingBoxes;
        unsigned int fNumShapes;
        unsigned int fTotalNumTris;
        unsigned int fTotalNumVerts;
        bool fUseCachedBuffers;
        double fBufferReadTime;
    };
}
{
public:
    static void* creator();
    static MStatus init3dViewPostRenderCallbacks();
 
    static const MString drawDbClassificationGeometry;
 
    static const MString drawDbClassificationSubScene;
 
    static const MString drawRegistrantId;
 
    static const char* nodeTypeName;
    static const char* selectionMaskName;
    enum CacheReadingState {
        kCacheReadingFile,
        kCacheReadingDone
    };
    ShapeNode();
    ~ShapeNode();
    virtual void postConstructor();
    virtual bool isBounded() const;
    virtual bool getInternalValueInContext(
const MPlug& plug,
 
    virtual bool setInternalValueInContext(
const MPlug& plug,
 
    virtual void copyInternalData(
MPxNode* source);
 
    virtual MStringArray    getFilesToArchive( 
bool shortName = 
false,
 
                                               bool unresolvedName = false,
                                               bool markCouldBeImageSequence = false ) const;
    virtual bool excludeAsPluginShape() const;
    void refreshCachedGeometry( bool clearFileCache = false );
    void refreshOtherCachedShapes( 
const MString& cacheFileName );
 
    
    const GPUCache::SubNode::Ptr& getCachedGeometry() const;
    const GPUCache::MaterialGraphMap::Ptr& getCachedMaterial() const;
    const CacheFileEntry::MPtr& getCacheFileEntry() const;
    const CacheFileEntry::BackgroundReadingState backgroundReadingState() const;
    
    
    void addedToModelCB();
    
    void removedFromModelCB();
    
    void timeChangeCB(double timeInSeconds);
    void updateGeomPath( 
const MString& validatedGeomPath ) 
const;
 
    bool canMakeLive() const;
    bool readBuffers(const SubNode::Ptr subNode, double seconds)const;
    void closestPoint(
const MPoint &toThisPoint, 
MPoint &theClosestPoint, 
double tolerance = 0.1);
 
    bool closestPoint( 
const MPoint &raySource, 
const MVector &rayDirection, 
MPoint &theClosestPoint, 
MVector &theClosestNormal, 
bool findClosestOnMiss, 
double tolerance=MPoint_kTol);
 
    unsigned int getIntersectionAccelerator(const gpuCacheIsectAccelParams& accelParams, double seconds) const;
    
    static void dirtyVP2Geometry( 
const MString& fileName );
 
private:
    
    ShapeNode(const ShapeNode& obj);
    const ShapeNode& operator=(const ShapeNode& obj);
    bool setInternalValues(
const MString& newFileName,
 
    
    bool    getEdgeSnapPoint(
const MPoint &rayPoint, 
const MVector &rayDirection, 
MPoint &theClosestPoint);
 
    mutable MString fResolvedCacheFileName;
 
    
    mutable ShapeNodePrivate::BufferCache* fBufferCache;
    mutable std::vector<gpuCacheSpatialSubdivision *> fSpatialSub;
    mutable GPUCache::SubNode::Ptr                   fCachedGeometry;
    mutable GPUCache::MaterialGraphMap::Ptr          fCachedMaterial;
    mutable CacheReadingState                        fCacheReadingState;
    mutable CacheFileEntry::MPtr                     fCacheFileEntry;
    MCallbackId fRemoveFromModelCallbackId;
    MCallbackId fTimeChangeCallbackId;
    static MCallbackId fsModelEditorChangedCallbackId;
};
class CacheShapeRegistry
{
public:
    typedef boost::unordered_multimap<MString, MObjectHandle, GPUCache::MStringHash> Map;
    ~CacheShapeRegistry();
    static CacheShapeRegistry& theCache();
    void                    getAll( std::vector<MObjectHandle>& shapes );
    void                    find(
const MString& key, std::vector<MObjectHandle>& shapes);
 
    void                    clear();
private:
    CacheShapeRegistry();
    static CacheShapeRegistry fsSingleton;
    static Map fMap;
};
class DisplayPref
{
public:
    enum WireframeOnShadedMode {
        kWireframeOnShadedFull,
        kWireframeOnShadedReduced,
        kWireframeOnShadedNone
    };
    static WireframeOnShadedMode wireframeOnShadedMode();
private:
    static void displayPrefChanged(void*);
    static WireframeOnShadedMode fsWireframeOnShadedMode;
    static MCallbackId fsDisplayPrefChangedCallbackId;
};
{
public:
    static void* creator();
    ShapeUI();
    ~ShapeUI();
    virtual void getDrawRequests(
const MDrawInfo & info,
 
                                 bool objectAndActiveOnly,
    
    
private:
    
    ShapeUI(const ShapeUI& obj);
    const ShapeUI& operator=(const ShapeUI& obj);
    
    
    
    enum DrawToken {
        kBoundingBox,
        kDrawWireframe,
        kDrawWireframeOnShaded,
        kDrawSmoothShaded,
        kDrawSmoothShadedDepthOffset
    };
};
}
#endif