#ifndef QRK_SCRIPTED_STATE_MACHINE_H
#define QRK_SCRIPTED_STATE_MACHINE_H

/*!
  \file
  \brief スクリプト駆動の状態遷移用テンプレート

  「ゲーム AI プログラミング」より

  \author Satofumi KAMIMURA

  $Id: ScriptedStateMachine.h 1813 2010-05-01 14:21:29Z satofumi $
*/

#include <luabind/luabind.hpp>
#include <stack>


namespace qrk
{
    //! スクリプト駆動の状態遷移用テンプレート
    template <class T>
    class ScriptedStateMachine
    {
    public:
        ScriptedStateMachine(T* owner) : owner_(owner)
        {
        }


        void setCurrentState(const luabind::object& state)
        {
            current_state_ = state;
        }


        void update()
        {
            if (current_state_.is_valid()) {
                current_state_["Execute"](owner_);
            }
        }


        void changeState(const luabind::object& next_state)
        {
            if (current_state_) {
                current_state_["Exit"](owner_);
            }

            state_stack_.push(current_state_);
            current_state_ = next_state;
            current_state_["Enter"](owner_);
        }


        void changePreviousState(void)
        {
            if (state_stack_.empty()) {
                return;
            }

            changeState(state_stack_.top());

            // 元からあった状態と changeState() で追加した状態の２つを取り除く
            state_stack_.pop();
            state_stack_.pop();
        }


        void popState(void)
        {
            state_stack_.pop();
        }


        const luabind::object& currentState(void) const
        {
            return current_state_;
        }

    private:
        T* owner_;
        luabind::object current_state_;
        std::stack<luabind::object> state_stack_;
    };
}

#endif /* !QRK_SCRIPTED_STATE_MACHINE_H */
