#include "gpuCacheGeometry.h"
#include <algorithm>
#include <cassert>
#include <limits>
#include <vector>
namespace {
    using namespace GPUCache;
    
    
    
    class NodeDataValidator : public SubNodeVisitor
    {
    public:
        NodeDataValidator() : fIsValid(false) {}
        bool isValid() const { return fIsValid; }
        virtual void visit(const XformData&   xform,
                           const SubNode&     )
        {
            fIsValid = !xform.getSamples().empty();
        }
        
        virtual void visit(const ShapeData&   shape,
                           const SubNode&     )
        {
            fIsValid = !shape.getSamples().empty();
        }
        
    private:
        bool fIsValid;
    };
    
}
namespace GPUCache {
SubNodeData::~SubNodeData()
{}
ShapeData::ShapeData()
{}
ShapeData::~ShapeData()
{}
const boost::shared_ptr<const ShapeSample>&
ShapeData::getSample(double seconds) const
{
    
    
    
    
    
    
    
    assert(!fSamples.empty());
    if (fSamples.empty()) {
        static const boost::shared_ptr<const ShapeSample> null;
        return null;
    }
    
    SampleMap::const_iterator it = fSamples.upper_bound(seconds);
    if (it != fSamples.begin()) {
        --it;
    }
    return it->second;
}
void ShapeData::addSample(
    const boost::shared_ptr<const ShapeSample>& sample)
{
    fSamples[sample->timeInSeconds()] = sample;
}
void ShapeData::accept(SubNodeVisitor& visitor,
                       const SubNode&  subNode) const
{
    return visitor.visit(*this, subNode);
}
void ShapeData::setMaterial(
const MString& material)
 
{
    assert(fMaterials.empty());
    fMaterials.push_back(material);
}
void ShapeData::setMaterials(const std::vector<MString>& materials)
{
    assert(fMaterials.empty());
    fMaterials = materials;
}
const std::vector<MString>& ShapeData::getMaterials() const
{
    return fMaterials;
}
XformData::~XformData()
{}
const boost::shared_ptr<const XformSample>&
XformData::getSample(double seconds) const
{
    
    assert(!fSamples.empty());
    if (fSamples.empty()) {
        static const boost::shared_ptr<const XformSample> null;
        return null;
    }
    SampleMap::const_iterator it = fSamples.upper_bound(seconds);
    if (it != fSamples.begin()) {
        --it;
    }
    return it->second;
}
void XformData::accept(SubNodeVisitor& visitor,
                       const SubNode&  subNode) const
{
    return visitor.visit(*this, subNode);
}
SubNodeVisitor::~SubNodeVisitor()
{}
SubNode::SubNode(
    const SubNodeData::Ptr& nodeData)
    : fName(name), fNodeData(nodeData), fTransparentType(kOpaque)
{
    
    NodeDataValidator validator;
    nodeData->accept(validator, *this);
    assert(validator.isValid());
}
SubNode::~SubNode()
{}
}