//---------------------------------------------------------------------------
#ifndef FSM_H
#define FSM_H
#include "behavioral.h"
#include <list>
//---------------------------------------------------------------------------
namespace hub {

// =====================================================================
class FsmProduct;

struct StateTableRow {
  std::string input;
  std::string currState;
  std::string nextState;
  std::string output;
};

class FsmState {
private:
  std::string name_;
  std::string output_;
public:
  std::list<FsmProduct*> products_;

  void name(std::string n) { name_ = n; }
  std::string name(void) { return name_; }
  void output(std::string o) { output_ = o; }
  std::string output(void) { return output_; }

  FsmState(std::string name):name_(name) {}
};

class FsmProduct {
private:
  std::string input_;
  std::string output_;
  FsmState* nextState_;
public:
  void input(std::string i) { input_ = i; }
  std::string input(void) { return input_; }
  void output(std::string o) { output_ = o; }
  std::string output(void) { return output_; }
  void nextState(FsmState* s) { nextState_ = s; }
  FsmState* nextState(void) { return nextState_; }

  FsmProduct(std::string i, std::string o, FsmState* ns):input_(i), output_(o), nextState_(ns) {}
};

// =====================================================================

class FsmDescr: public BehavDescr {
private:
  int inputNo_;
  int outputNo_;
  int stateNo_;
  int productNo_;
  std::string type_; //"Moore" or "Mealy"
  std::list<FsmState*> states_;
  std::list<FsmProduct*> products_;
  std::list<FsmProduct*> dontcareCurrStates_;
  std::list<FsmProduct*> dontcareNextStates_;
  FsmState* resetState_;
public:
  std::string getDescrName(void) { return "KISS" + type_; }
  void setType(std::string t) { type_ = t; }
  std::string getType(void) { return type_; }
  void inputNo(int n) { inputNo_ = n; }
  int inputNo(void) { return inputNo_; }
  void outputNo(int n) { outputNo_ = n; }
  int outputNo(void) { return outputNo_; }
  void stateNo(int n) { stateNo_ = n; }
  int stateNo(void) { return stateNo_; }
  void productNo(int n) { productNo_ = n; }
  int productNo(void) { return productNo_; }
  void resetState(std::string st);
  FsmState* resetState(void) { return resetState_; }

  FsmState* FindOrCreateState(std::string &name);
  FsmProduct* FindOrCreateProduct(std::string& input, std::string& output, FsmState* nextState);

  FsmState* CreateMealyFromTable(std::list<StateTableRow>& table);
  void CreateTable(std::list<StateTableRow>& table);

  FsmDescr(): inputNo_(0), outputNo_(0), stateNo_(0), productNo_(0), type_("Mealy"), resetState_(NULL) {}
  FsmDescr(int inpN, int outN, std::list<hub::StateTableRow>& table, std::string reset, int stateCount, int productCount);
  
  void clear (void);                            // resets all af if the implicit ctor executed
  FsmDescr& copy (const FsmDescr&);             // deep copy, assignment JS
  ~FsmDescr ();                                 // JS
};
// ---------------------------------------------------------------------
class FsmAgent: public BehavAgent {
private:
  FsmDescr repr_;
public:
  virtual bool Eq (const BehavDescr*) const;		// compare func equivalence
  virtual BehavDescr* CreateDescr (void) const;	    // create log representation

  FsmAgent(int inpN, int outN, std::list<hub::StateTableRow>& table, std::string reset, int stateCount, int productCount):
    repr_(inpN, outN, table, reset, stateCount, productCount) {};
};

}
//---------------------------------------------------------------------------
#endif
