#pragma once

#include <utility>
#include <map>
#include <vector>

#include "../Memory/ref_ptr.h"
#include "input_handler.h"
#include "condition.h"

namespace roy {

    namespace ih {

        class state_machine_ih : public input_handler
        {
        protected:
            typedef roy::memory::ref_ptr<input_handler> ref_ptr_IH;
            typedef roy::memory::ref_ptr<condition> ref_ptr_Cdt;
            typedef std::pair<ref_ptr_Cdt, ref_ptr_IH> pair;
            typedef std::vector<pair> vector;
            typedef std::map<ref_ptr_IH, vector> map;

        public:
            virtual bool    OnLButtonDown(UINT nFlags, CPoint point);
            virtual bool    OnLButtonUp(UINT nFlags, CPoint point);
            virtual bool    OnLButtonDblClk(UINT nFlags, CPoint point);

            virtual bool    OnRButtonDown(UINT nFlags, CPoint point);
            virtual bool    OnRButtonUp(UINT nFlags, CPoint point);
            virtual bool    OnRButtonDblClk(UINT nFlags, CPoint point);

            virtual bool    OnMButtonDown(UINT nFlags, CPoint point);
            virtual bool    OnMButtonUp(UINT nFlags, CPoint point);
            virtual bool    OnMButtonDblClk(UINT nFlags, CPoint point);

            virtual bool    OnMouseWheel(UINT nFlags, short zDelta, CPoint point);

            virtual bool    OnMouseMove(UINT nFlags, CPoint point);

            virtual bool    OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
            virtual bool    OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);

            virtual void    OnEntering(void);
            virtual void    OnLeaving(void);

        public:
            void            SetInitialState(const ref_ptr_IH& ih);
            void            AddStateTranslation(const ref_ptr_IH& former, const ref_ptr_Cdt& cdt, const ref_ptr_IH& later);
            void            Clear(void);

        protected:
            void            Switch(const ref_ptr_IH& later);
            void            Enter(ref_ptr_IH& ih);
            void            Leave(ref_ptr_IH& ih);
        
        protected:
            map             _map;
            ref_ptr_IH       _current_ih;
        };

    }

}

