#include "state_machine_ih.h"

#include <afxwin.h>

namespace roy {

    namespace ih {

        bool state_machine_ih::OnLButtonDown(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnLButtonDown(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnLButtonDown(nFlags, point);
        }

        bool state_machine_ih::OnLButtonUp(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnLButtonUp(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnLButtonUp(nFlags, point);
        }

        bool state_machine_ih::OnLButtonDblClk(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnLButtonDblClk(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnLButtonDblClk(nFlags, point);
        }

        bool state_machine_ih::OnRButtonDown(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnRButtonDown(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnRButtonDown(nFlags, point);
        }

        bool state_machine_ih::OnRButtonUp(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnRButtonUp(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnRButtonUp(nFlags, point);
        }

        bool state_machine_ih::OnRButtonDblClk(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnRButtonDblClk(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnRButtonDblClk(nFlags, point);
        }

        bool state_machine_ih::OnMButtonDown(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnMButtonDown(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnMButtonDown(nFlags, point);
        }

        bool state_machine_ih::OnMButtonUp(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnMButtonUp(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnMButtonUp(nFlags, point);
        }

        bool state_machine_ih::OnMButtonDblClk(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnMButtonDblClk(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnMButtonDblClk(nFlags, point);
        }

        bool state_machine_ih::OnMouseWheel(UINT nFlags, short zDelta, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnMouseWheel(nFlags, zDelta, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnMouseWheel(nFlags, zDelta, point);
        }

        bool state_machine_ih::OnMouseMove(UINT nFlags, CPoint point)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnMouseMove(nFlags, point);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnMouseMove(nFlags, point);
        }

        bool state_machine_ih::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnKeyDown(nChar, nRepCnt, nFlags);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnKeyDown(nChar, nRepCnt, nFlags);
        }

        bool state_machine_ih::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            for (vector::iterator it = _map[_current_ih].begin(); it != _map[_current_ih].end(); it++) {
                it->first->OnKeyUp(nChar, nRepCnt, nFlags);
                if (it->first->is_valid()) {
                    Switch(it->second);
                    break;
                }
            }
            return _current_ih->OnKeyUp(nChar, nRepCnt, nFlags);
        }

        void state_machine_ih::OnEntering(void)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            _current_ih->OnEntering();
        }
        
        void state_machine_ih::OnLeaving(void)
        {
            if (_current_ih == NULL) {
                assert(false);
            }

            _current_ih->OnLeaving();
        }

        void state_machine_ih::SetInitialState(const ref_ptr_IH& ih)
        {
            if (_current_ih != NULL) {
                assert(false);
            }

            _current_ih = ih;
            Enter(_current_ih);
        }

        void state_machine_ih::AddStateTranslation(const ref_ptr_IH& former, const ref_ptr_Cdt& cdt, const ref_ptr_IH& later)
        {
            _map[former].push_back(std::make_pair(cdt, later));
        }

        void state_machine_ih::Clear(void)
        {
            _map.clear();
        }

        void state_machine_ih::Switch(const ref_ptr_IH& later)
        {
            Leave(_current_ih);
            _current_ih = later;
            Enter(_current_ih);
        }

        void state_machine_ih::Enter(ref_ptr_IH& ih)
        {
            ih->OnEntering();
            for (vector::iterator it = _map[ih].begin(); it != _map[ih].end(); it++) {
                it->first->OnEntering();
            }
        }

        void state_machine_ih::Leave(ref_ptr_IH& ih)
        {
            ih->OnLeaving();
            for (vector::iterator it = _map[ih].begin(); it != _map[ih].end(); it++) {
                it->first->OnLeaving();
            }
        }

    }

}
