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

//=============================================================================
/**
 *  @file    b_state.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_STATE_H
#define B_STATE_H

#include "b_ace.h"
#include "b_value.h"

// Forward declaration
class b_state;
class b_trigger;
class b_context;
class b_transition;

typedef vector<b_state *, allocator<b_state *> >  b_states;

extern int strRelation(const BCHAR * p1, const BCHAR * p2, int * retpos = NULL);

//-----------------------------------------------------------------------------
//
// State Type
//
//-----------------------------------------------------------------------------
class BEE_Export b_statype
{
    friend class b_state;

public:
    enum { EDGE, CONDITION, HISTORY, FIXED, AND_NODE, ROOT_NODE };
    //
    b_statype(const BCHAR * name, int type)
            : m_name(name), m_type(type), m_default(""), m_idx(0) {}
    b_statype(const BCHAR * name, const BCHAR * init, int type)
            : m_name(name), m_type(type), m_default(init), m_idx(0) {}
    b_statype(const BCHAR * name, int type, int id, const BCHAR * init)
            : m_name(name), m_type(type), m_default(init), m_idx(id) {}
    virtual ~b_statype() {}

    virtual b_state * create(b_context * root) = 0;

    void  name(const string& nstr) { m_name = nstr; }
    const string& name() const     { return m_name; }
    const BCHAR * charName() const { return m_name.c_str(); }
    const string& defState() const { return m_default; }
    bool isEdge() const        { return (m_type == EDGE); }
    bool isConditional() const { return (m_type == CONDITION); }
    bool isHistorical() const  { return (m_type == HISTORY); }
    bool isFixed() const       { return (m_type == FIXED); }
    bool isAnd() const         { return (m_type == AND_NODE); }
    bool isRoot() const        { return (m_type == ROOT_NODE); }
    void setIdx(int id)        { m_idx = id; }
    void dump() const {
            ACE_DEBUG((LM_DEBUG, ACE_TEXT("state type(%s: %d)\n"),
                                 this->m_name.c_str(), m_type));
        }

protected:
    b_statype() : m_name(_TX("")), m_type(EDGE), m_default(_TX("")), m_idx(0) {}
    int  getIdx()       { return m_idx; }
//
protected:
    string m_name;
    int    m_type;
    string m_default;
    int    m_idx;
};

//-----------------------------------------------------------------------------
//
// Node State
//
//-----------------------------------------------------------------------------
template<class T>
class b_edge : public b_statype
{
public:
    b_edge(const BCHAR * name) : b_statype(name, EDGE) {}
    b_edge(const BCHAR * name, int id) : b_statype(name, EDGE, id) {}
    virtual ~b_edge() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }
};

//-----------------------------------------------------------------------------
template<class T>
class b_condstate : public b_statype
{
public:
    b_condstate(const BCHAR * name): b_statype(name, CONDITION) {}
    virtual ~b_condstate() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }

};

//-----------------------------------------------------------------------------
template<class T>
class b_histate : public b_statype
{
public:
    b_histate(const BCHAR * name, const BCHAR * init)
            : b_statype(name, init, HISTORY) {}
    virtual ~b_histate() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }
};

//-----------------------------------------------------------------------------
template<class T>
class b_fixstate : public b_statype
{
public:
    b_fixstate(const BCHAR * name, const BCHAR * first)
            : b_statype(name, first, FIXED) {}
    virtual ~b_fixstate() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }

private:
};

//-----------------------------------------------------------------------------
template<class T>
class b_andstate : public b_statype
{
public:
    b_andstate(const BCHAR * name): b_statype(name, AND_NODE) {}
    virtual ~b_andstate() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }

};

//-----------------------------------------------------------------------------
template<class T>
class b_rootstate : public b_statype
{
public:
    b_rootstate(const BCHAR * name): b_statype(name, ROOT_NODE) {}
    virtual ~b_rootstate() {}

    virtual b_state * create(b_context * root) {
            return new T(this, root);
        }

};


//-----------------------------------------------------------------------------
//
// State
//
//-----------------------------------------------------------------------------
class b_state;
typedef b_edge<b_state>  EdgeState;

//-----------------------------------------------------------------------------
class BEE_Export b_state
{
    friend class b_context;

public:
    enum  // Relationship of states
    {
        OTHER_STATE = -1,
        SAME_STATE = 0,
        DESCENT_STATE = 1,
        ANCESTOR_STATE = 2,
        COUSIN_STATE = 3
    };

    b_state(b_statype * base, b_context * root)
            : m_base(base), m_root(root), m_parent(NULL), m_trigger(false) {}
    virtual ~b_state() {}

    virtual int  begin(b_state * , b_trigger * ) { return 0; }
    virtual int  end(b_trigger * ) { return 0; }
    virtual int  pass() { return 0; }
    virtual const BCHAR * next(b_trigger * ) { return NULL; }
    virtual int  transit(b_state * , b_state * ) { return 0; }
    virtual void dump() const;

    const string& name() const     { return m_base->name(); }
    const BCHAR * charName() const { return m_base->charName(); }
    void name(string& namestr) { m_base->name(namestr); }
    bool isEdge() const        { return m_base->isEdge(); }
    bool isConditional() const { return m_base->isConditional(); }
    bool isHistorical() const  { return m_base->isHistorical(); }
    bool isFixed() const       { return m_base->isFixed(); }
    bool isAnd() const         { return m_base->isAnd(); }
    bool isRoot() const        { return m_base->isRoot(); }
    int  idx() const           { return m_base->getIdx(); }
    b_context * table() const  { return m_root; }
    b_state * parent() const   { return m_parent; }
    void parent(b_state * ps)  { m_parent = ps; }
    int  relationship(b_state * dest, string& next);
    bool isChild(const string& next);
    bool isDescendant(const string& next);

    static EdgeState Null;

protected:
    b_state() : m_base(NULL), m_root(NULL), m_parent(NULL), m_trigger(false) {}
//
protected:
    b_statype * m_base;
    b_context * m_root;
    b_state * m_parent;           // the parent state
    bool      m_trigger;          // The node has trigger or not
    vector<b_transition *> m_transitions;
};


//-----------------------------------------------------------------------------
//
// Terminate state
template<class T>
class b_edgenode : public b_state
{
public:
    b_edgenode() : b_state() {}
    b_edgenode(b_statype * base, b_context * root) : b_state(base, root) {}
    virtual ~b_edgenode() {}

    // Must re-define in root class
    virtual int  begin(b_state * prev, b_trigger * trig) {
            ACE_UNUSED_ARG(prev);
            ACE_UNUSED_ARG(trig);
            return 0;
        }
    virtual int  end(b_trigger * trig) {
            ACE_UNUSED_ARG(trig);
            return 0; 
        }

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

#endif

