#ifndef __OSGCAL__MODEL_H__
#define __OSGCAL__MODEL_H__

#include <osg/Geode>
#include <cal3d/cal3d.h>
#include <osgCal/CoreModel>
#include <osgCal/Export>

namespace osgCal {

/** @class osgCal::Model
 * @brief Adapter that allows having a model in the scenegraph.
 *
 * This class is an osg::Node so you can add it to your scenegraph. Moreover
 * it handles automatically updating the cal3d model associated, and the
 * generation of drawables binded to submeshes of the model.
 *
 * Note that this node installs an UpdateCallback so don't overwrite it...
 */
class OSGCAL_EXPORT Model: public osg::Geode {
public:
    Model();
    Model(CoreModel *core);

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

    /** 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 Model*>(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 "Model"; }

    inline ~Model() { model.destroy(); }

    /**
     * Create an "instance" of the reference (core) model given.
     * This method creates lots of drawables each one with a single
     * material, to take advantage of OSG state sorting.
     */
    void create(CoreModel *core);

    /**
     * Starts an animation with max strength over other animations
     * @param id The animation id
     * @param delay_in Time to reach max strength at begining of animation
     * @param delay_out Time to leave max strength at end of animation
     */
    void action(unsigned id, float delay_in, float delay_out);

    /**
     * Starts an animation in loop mode
     * @param id The animation id
     * @param weigth The strength of the loop (there can be several simultaneous)
     * @param delay Time to reach the indicated weigth
     */
    void loop(unsigned id, float weight, float delay);

    /**
     * Stops an animation
     * @param id The animation id
     * @param delay Time to fade out
     */
    void stop(unsigned id, float delay);

    /**
     * Number of animations in this model
     */
    inline unsigned animationCount() {
	return model.getCoreModel()->getCoreAnimationCount();
    }

    /**
     * Get the core model
     */
    const CoreModel *getCoreModel() const { return coreModel.get(); }
private:
    CalModel model;
    osg::ref_ptr<CoreModel> coreModel;
};

}; // namespace osgCal

#endif
