#ifndef __OSGCAL__CORE_MODEL_H__
#define __OSGCAL__CORE_MODEL_H__

#include <vector>
#include <osg/Texture2D>
#include <osg/Referenced>
#include <osgCal/Export>
#include <cal3d/cal3d.h>

namespace osgCal {

/** @class osgCal::CoreModel
 * @brief Adapter that enables reference-counting of core models
 * A core model is a reference (a template) for creating real models. This
 * allows sharing lot of data, like the base geometry (the geometry before
 * deforming any vertex)
 */
class OSGCAL_EXPORT CoreModel: public osg::Object {
public:
    CoreModel();

    virtual osg::Object* cloneType() const { return new CoreModel(); }

    /** Clone the an object, with Object* return type.
     Must be defined by derived classes.*/
    virtual osg::Object* clone(const osg::CopyOp&) const;

    virtual bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast<const CoreModel*>(obj) != 0; }

    /** return the name of the object's library. Must be defined
     by derived classes. The OpenSceneGraph convention the is
     that the namspace of a library is the same as the library name.*/
    virtual const char* libraryName() const { return "osgCal"; }

    /** return the name of the object's class type. Must be defined
     by derived classes.*/
    virtual const char* className() const { return "CoreModel"; }
    
    /**
     * Loads the skeleton of the model
     */
    void loadSkeleton(std::string skeleton_file);

    /**
     * Loads one animation. You can load several.
     */
    void loadAnimation(std::string animation_file);

    /**
     * Loads one mesh. You can load several.
     */
    void loadMesh(std::string mesh_file);

    /**
     * Loads one material. You can load several, in fact you can load
     * several for each mesh, as each mesh can have submeshes.
     */
    void loadMaterial(std::string material_file);

    /** Loads all the textures referenced by some material. You can
     * specify some directory, if not, current will be used */
    void loadAllTextures(std::string directory=".");

    inline ~CoreModel() { coreModel.destroy(); }

    /* Get a pointer to the real core model, *DONT* keep pointers to
     * it. Instead, keep references to this class (osgCal::CoreModel). */
    CalCoreModel *get() { return &coreModel; }

    std::string getSkeletonFileName() const { return skeleton; }
    const std::vector<std::string> getAnimationFileNames() const { return animations; }
    const std::vector<std::string> getMeshFileNames() const { return meshes; }
    const std::vector<std::string> getMaterialFileNames() const { return materials; }
private:
    CalCoreModel coreModel;
    /** List of textures loaded by this class, to destroy them when this class
     * is destroyed. */
    std::vector< osg::ref_ptr<osg::Texture2D> > textures;

    std::string skeleton;
    std::vector< std::string > animations;
    std::vector< std::string > meshes;
    std::vector< std::string > materials;
};

}; // namespace osgCal

#endif
