// $Id: b_statenode.h,v 1.4 2003/03/16 14:51:00 fukasawa Exp $

//=============================================================================
/**
 *  @file    b_statenode.h
 *
 *  @author Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 1998-2003 BEE Co.,Ltd. All rights reserved.
 *
 * 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.
 */
//=============================================================================

#ifndef B_STATENODE_H
#define B_STATENODE_H

#include "state/b_state.h"

//-----------------------------------------------------------------------------
//
// State Node
//
//-----------------------------------------------------------------------------
class BEE_Export b_statenode : public b_state
{
    friend class b_state;
    friend class b_context;

public:
    virtual ~b_statenode() {}

    virtual int transit(b_state * prev, b_state * dest);
    virtual int pass() { m_before = m_current; return 0; }
    virtual const BCHAR * next(b_trigger * )  { return NULL; }
    virtual const string& current(int = 0) const { return m_current; }
    virtual void  append(b_state * substate) { m_substates.push_back(substate); }
    virtual void  dump() const;

    int  subCount() const { return m_substates.size(); }
    int  nodeNum() const  { return m_nodeNum; }
    void nodeNum(int num) { m_nodeNum = num; }
    bool usedAnd() const  { return (m_nodeNum >= 0); }
    void set(b_statype * base, b_context * root);

protected:
    virtual void change(b_state * ps) { m_current = ps->name(); }
    b_statenode(b_statype * base, b_context * root);
    b_statenode() : m_current(_TX("")), m_next(_TX("")), m_nodeNum(0),
                    m_before(_TX("")) {}

//
protected:
    string m_current;                  // current state
    string m_next;                     // next state
    b_states m_substates;              // sub-state objects
    int    m_nodeNum;                  // sequence number in and node
    string m_before;                   // for history
};

//
// Condition State
//
template<class T>
class b_condnode : public b_statenode
{
public:
    b_condnode() : b_statenode() {}
    b_condnode(b_statype * base, b_context * root) : b_statenode(base, root) {}
    virtual ~b_condnode() {}

    // Must re-define in root class
    virtual const BCHAR * next(b_trigger * trigger)   { return NULL; }

    inline T * root() { return (T *)m_root; }
};

//
// History State
//
class BEE_Export b_histnode : public b_statenode
{
    friend class b_context;

public:
    b_histnode(b_statype * base, b_context * root): b_statenode(base, root) {}
    virtual ~b_histnode() {}

    virtual const BCHAR * next(b_trigger * trigger);

protected:
};

typedef b_histate<b_histnode>  HistState;

//
// Fixed State Node
//
class BEE_Export b_fixnode : public b_statenode
{
    friend class b_context;

public:
    b_fixnode(b_statype * base, b_context * root): b_statenode(base, root) {}
    virtual ~b_fixnode() {}

    virtual int   begin(b_state * prev, b_trigger * trig);
    virtual const BCHAR * next(b_trigger * trigger);

protected:
};

typedef b_fixstate<b_fixnode>  FixState;

//
// And Node State
//
class BEE_Export b_andnode : public b_statenode
{
    friend class b_rootnode;
    friend class b_context;

public:
    b_andnode(b_statype * base, b_context * root): b_statenode(base, root) {}
    virtual ~b_andnode() {}

    virtual const string& current(int num = 0) const;
    virtual int  begin(b_state * prev, b_trigger * trigger);

    virtual void append(b_state * node) {
            m_substates.push_back(node);
            if (! node->isEdge()) {
                ((b_statenode *)node)->nodeNum(m_substates.size() - 1);
            }
        }

};

typedef b_andstate<b_andnode>  AndState;

//
// Root Node State
//
class BEE_Export b_rootnode : public b_statenode
{
    friend class b_context;

public:
    b_rootnode(b_statype * base, b_context * root);
    virtual ~b_rootnode() {}

    virtual const string& current(int num = 0) const;
    int     size() const { return m_states.size(); }

protected:
    virtual void change(b_state * ps);
    b_rootnode() : b_statenode() {}

//
protected:
    vector<string> m_states;
};

typedef b_rootstate<b_rootnode>  RootState;

#endif
