/* -*- c++ -*-
 *
 * Copyright (C) 2004 Mekensleep
 *
 *	Mekensleep
 *	24 rue vieille du temple
 *	75004 Paris
 *       licensing@mekensleep.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Authors:
 *  Loic Dachary <loic@gnu.org>
 *
 */

#ifndef BETSLIDER
#define BETSLIDER

#include <osg/Vec4>
#include <osg/Group>
#include <osgDB/ReaderWriter>

#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
	#  ifdef BETSLIDER_LIBRARY
	#    define BETSLIDER_EXPORT   __declspec(dllexport)
	#  else
	#    define BETSLIDER_EXPORT   __declspec(dllimport)
	#  endif /* BETSLIDER_LIBRARY */
#else
	#  define BETSLIDER_EXPORT
#endif

extern "C" {
  struct _xmlDoc;
}

namespace osg {
  class Geode;
  class Geometry;
  class PositionAttitudeTransform;
};

namespace osgText {
  class Text;
  class Font;
};

namespace betslider {

  class BETSLIDER_EXPORT BetSlider : public osg::Group {
  public:
    enum RowIndex {
      ROW_CANCEL = 0,
      ROW_CALL,
      ROW_RAISE,
      ROW_RAISE_MAX,
      ROW_CURRENT_AMOUNT,
      ROW_COUNT
    };

    enum SideIndex {
      SIDE_LEFT = 0,
      SIDE_RIGHT,
      SIDE_COUNT
    };

    META_Node(betslider, BetSlider)

    BetSlider();
    BetSlider(const BetSlider&, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);

  protected:
    virtual ~BetSlider();

  public:
    void setFont(int side_index, osgText::Font* font, float font_size);
    void setNormalColor(int row_index, int side_index, const osg::Vec4& color);
    void setSelectedColor(int row_index, int side_index, const osg::Vec4& color);
    void setSeparator(osg::Geode* separator);
    void setCursor(osg::Geode* cursor);
    void setBackgroundColor(int side_index, const osg::Vec4& background_color);
    void setMiddleColor(const osg::Vec4& middle_color);
    void setMiddleWidth(float middle_width);
    void setMotorFixedLength(float motor_fixed_length) { _motor_fixed_length = motor_fixed_length; }
    void setMotorVariableLength(float motor_variable_length) { _motor_variable_length = motor_variable_length; }
    void setMargin(float margin);

    void setLimits(unsigned int call, unsigned int raise, unsigned int raise_max, unsigned int all_in, unsigned int pot, unsigned int step);

    unsigned int moveCursor(float delta);

    unsigned int getCurrentValue();
    
    bool unserialize(struct _xmlDoc* doc, const osgDB::ReaderWriter::Options* options);
    bool unserialize(const std::string& fileName, const osgDB::ReaderWriter::Options* options);
    bool serialize(const std::string& fileName) const;

  protected:
    class Row : public Referenced {
    public:
      Row(osg::Group* group, osg::Geode* geode, bool left, bool right, const osg::PositionAttitudeTransform* separator);

      void setText(const std::string& left, const std::string& right);
      void setMotorRange(float& origin, float length);
      void setCursorRange(float& origin, float& cursor, float height);
      void setValueRange(unsigned int value_start, unsigned int value_end) {
	_value_start = value_start;
	_value_end = value_end;
      }
      void setSeparator(osg::PositionAttitudeTransform* separator);
      osg::BoundingBox getBound() const;
      void add();
      void remove();
      void selected();
      void unselected();

    protected:
      ~Row();

    public:
      bool _defines_range;
      bool _active;
      bool _variable;
      unsigned int _value_start;
      unsigned int _value_end;
      float _cursor_start;
      float _cursor_end;
      float _motor_start;
      float _motor_end;
      osg::ref_ptr<osg::Geode> _geode;
      osg::ref_ptr<osgText::Text> _text[SIDE_COUNT];
      osg::Vec4 _normal[SIDE_COUNT];
      osg::Vec4 _selected[SIDE_COUNT];
      osg::ref_ptr<osg::Group> _group;
      osg::ref_ptr<osg::PositionAttitudeTransform> _separator;
    };
    
    void layout();
    void build();
    Row* getCurrentRow();
    void setMotorPosition(float motor_position);
    void updateCursorPosition();
    void updateCurrentValue();

    osg::ref_ptr<osg::Geode> _geode;
    osg::ref_ptr<osg::Geometry> _background;
    osg::Vec4 _background_color[SIDE_COUNT];
    osg::Vec4 _middle_color;
    float _middle_width;
    typedef std::vector<osg::ref_ptr<Row> > Rows;
    Rows _rows;
    osg::ref_ptr<osgText::Font> _font[SIDE_COUNT];
    float _font_size[SIDE_COUNT];
    float _height;
    float _margin;
    float _motor_span;
    float _motor_position;
    float _motor_fixed_length;
    float _motor_variable_length;
    float _cursor_position;
    unsigned int _value_step;
    osg::ref_ptr<osg::PositionAttitudeTransform> _separator;
    osg::ref_ptr<osg::PositionAttitudeTransform> _cursor;
  };

} // namespace betslider

#endif // BETSLIDER
