#ifndef __MRPLIB_H
#define __MRPLIB_H

#ifndef __AUTOMASK_H
#include <automask.h>
#endif

#ifndef __ASSOC_H
#include <assoc.h>
#endif

#ifndef __DBLIB_H
#include "../db/dblib.h"
#endif
#ifndef __MGLIB_H
#include "../mg/mglib.h"
#endif


class TMRP_array : public TObject
{
  TAssoc_array _by_key;
  TPointer_array _by_idx;

  void swap(long i, long j) { _by_idx.swap(int(i), int(j)); }

protected:
  TToken_string _key;  // Token string di lavoro

  virtual TSortable* new_obj(const TToken_string& key) const pure;
  TSortable* add_obj(const TToken_string& key);
  TSortable* find_obj(const TToken_string& key) const
  { return (TSortable*)_by_key.objptr(key); }
  TSortable& find_obj(long n) const 
  { return (TSortable&)_by_idx[int(n)]; }

public:
  long items() const { return _by_key.items(); }
  void destroy();
  long sort();
  void add(TMRP_array &a, bool force=FALSE);

  // I metodi add(), find() e operator[] devono essere dichiarati
  // dalle classi derivate e ritornare i tipi giusti tramite cast
  // TSortable* add(const char* key, bool create) 
  // { return (TSortable*)add_obj(key); }
  // TSortable* find(const char* key) const 
  // { return (TSortable*)find_obj(key); }
  // TSortable& operator[](long index) const 
  // { return (TSortable&)*find_obj(index); }
  TMRP_array & operator=(const TMRP_array& a);

  TMRP_array() { }
  TMRP_array(const TMRP_array& a);
  virtual ~TMRP_array() { }
};

class TMRP_calendar : public TObject
{
  static TString16 _days;
  static TToken_string _holidays;
  int _inizturno[8];
  int _lungturno[8];
  int _persturno[8];

  TAssoc_array _exc_imp, _exc_lin;
  TString16 _codimp, _codlin;

protected:
  void init_default();
  void read_cal(const TString& key, char tipo);
  int write_cal(char tipo) const;
  int remove_cal(const TString& code, char tipo) const;

public:
  int turni(const TDate& date, int& mini, int& maxi, bool as_is = FALSE);

  int turni_min(const TDate& date) 
  { int mini, maxi; turni(date, mini, maxi); return mini; }
  
  int turni_max(const TDate& date) 
  { int mini, maxi; turni(date, mini, maxi); return maxi; }

  // ore minime e massime ad una certa data
  int add_oremacchina(real & var,const TDate& date, bool max=FALSE);
  int add_oremacchina_max(real & var,const TDate& date);

  int add_oreuomo(real & var,const TDate& date, bool max=FALSE);
  int add_oreuomo_max(real & var,const TDate& date);

  TDate& next_working_day(TDate& from, int gap = 1);
  TDate& prev_working_day(TDate& from, int gap = 1)
  { return next_working_day(from, -gap); }
  
  int set_turni(const TDate& date, int mini, int maxi);
  
  int write() const;
  int rewrite() const { return write(); }
  int remove() const;

  void declare_holiday(int g, int m);
  void suppress_holiday(int g, int m);
  bool is_holiday(int g, int m) const;
  bool is_holiday(const TDate& date) const;
  bool is_red(const TDate& date) const;

  void set(const char* linea = NULL, const char* impianto = NULL);
  const TString& linea() const { return _codlin; }
  const TString& impianto() const { return _codimp; }
  char tipo() const;

  TMRP_calendar(const char* linea = NULL, const char* impianto = NULL);
  virtual ~TMRP_calendar() { }
};

class TCalendar_field : public TWindowed_field
{         
protected: // TWindowed_field
  virtual TField_window* create_window(int x, int y, int dx, int dy, 
                                       WINDOW parent);
public:
  void set_calendar(TMRP_calendar* cal, int year = 0);

  TCalendar_field(TMask* m) : TWindowed_field(m) { }
  virtual ~TCalendar_field() { }
};

class TCalendar_mask : public TAutomask
{
  TMRP_calendar _calendar;

protected:
  virtual TMask_field* parse_field(TScanner& scanner);
//  void make_profile_name(TFilename& f) const;

public:
  TMRP_calendar& calendar() { return _calendar; }
//  void save_profile();
//  void load_profile();

  const TMRP_calendar& calendar() const { return _calendar; }
  void update_calendar(short calendar, short year, short plant = 0, short line = 0);

  TCalendar_mask(const char* name, int num = 0);
  virtual ~TCalendar_mask() {};
};


class TMRP_time : public TSortable
{
  static TAssoc_array _frate_indovino;

  TString8 _imp, _lin;
  TDate _date;
  int _hour;

  TMRP_calendar& calendario();
  void copy(const TMRP_time& t) { set(t._date, t._hour, t._imp, t._lin); }

public: 
  static TMRP_calendar& get_calendar(const char* codimp=NULL,const char* ccodlin=NULL);

  const TString& impianto() const {return _imp;}
  const TString& linea() const    {return _lin;}
  const TDate& date() const { return _date; }
  int hour() const { return _hour; }

  virtual int compare(const TSortable& s) const;

  TMRP_time& add_time(int days, long hours = 0, bool macchina=TRUE);
  TMRP_time& sub_time(int days, long hours = 0, bool macchina=TRUE) { return add_time(-days, -hours,macchina); }

  void set(const TDate& d, int h, const char* imp, const char* lin);
  TMRP_time& operator=(const TMRP_time& t) { copy(t); return *this; }

  
  TMRP_time();
  TMRP_time(const TDate& d, int h, const char* imp, const char* lin);
  TMRP_time(const TMRP_time& t) { copy(t); }
  virtual ~TMRP_time() { } 
};

class TMRP_config : public TConfig
{
protected:
  void set_inizio_turno(int t,int time);
  void set_durata_turno(int t,int  time);

public:
  // **
  void set_inizio_turno(int t,int ore, int minuti);
  void set_durata_turno(int t,int ore, int minuti);
  void set_numpers_turno(int t, int  pers) {set("NUMPERS", pers, "mr", TRUE, t);}
  void set_turni(int n) {set("NTURNI", n, "mr", TRUE);}
  void set_gestimpianti(bool gi) {set("GESTIMPIANTI", gi ? "X" : "", "mr", TRUE); }

  // **
  int  inizio_turno(int t);
  int  durata_turno(int t);
  // **
  int ora_inizio_turno(int t);
  int min_inizio_turno(int t);
  int ore_durata_turno(int t);
  int min_durata_turno(int t);
  int num_turni() {return get_int("NTURNI", "mr");}
  int numpers_turno(int t);
  bool gestimpianti() {return get_bool("GESTIMPIANTI","mr"); }

  TMRP_config() :  TConfig(CONFIG_DITTA,"mr") {}
  virtual ~TMRP_config() {}
};

class TUnita_produttiva : public TRectype
{
  const char *erre1(int t); // campo durata e inizio turno
  const char *erre2(int t); // numero persone
protected:
  void set_inizio_turno(int t,int time);
  void set_durata_turno(int t,int  time);

public:

  const char * codice() const {return get("CODTAB");}
  const char * descr() const {return get("S0");}

  int  raw_numpers_turno(int t) ;
  // **
  void set_inizio_turno(int t,int ore, int minuti);
  void set_durata_turno(int t,int ore, int minuti);
  void set_numpers_turno(int t, int  pers);

  virtual int num_turni() {return get_int("I0");}
  virtual int  inizio_turno(int t);
  virtual int  durata_turno(int t);
  // **
  int ora_inizio_turno(int t);
  int min_inizio_turno(int t);
  int ore_durata_turno(int t);
  int min_durata_turno(int t);
  // numero di persone sul turno
  virtual int numpers_turno(int t) ;
  // flag di personale dedicato 
  virtual bool personale_dedicato() const { return get_bool("B0"); } 

  virtual const char * codmagdep() const { return get("S7"); }
  virtual const char * codmagdep_coll() const { return get("S8"); }
  const char * codmag() const ;
  const char * coddep() const ;

  virtual TRectype & operator=(const TRectype& rec);

  TUnita_produttiva(const TUnita_produttiva& rec) : TRectype (rec){}
  TUnita_produttiva(const TRectype& rec) : TRectype (rec){}
  TUnita_produttiva() : TRectype (LF_TAB){}
  virtual ~TUnita_produttiva() { }
};

class TImpianto : public TUnita_produttiva
{
protected:
  TObject* dup() const { return new TImpianto(*this); }

public:
  virtual TRectype & operator=(const TRectype& rec);
  // **
  TImpianto(const char* cod = "") ;
  TImpianto(const TRectype& rec) : TUnita_produttiva (rec) {}
  TImpianto(const TImpianto& rec) : TUnita_produttiva (rec){}
  virtual ~TImpianto() { }
};

class TLinea_prod : public TUnita_produttiva
{
protected:
  TObject* dup() const { return new TLinea_prod(*this); }
public:
  TImpianto * get_impianto() const;
  // **
  const char * codimp() const;
  virtual const char * codmagdep() const ;
  virtual const char * codmagdep_coll() const ;
  bool to_check() const {return !get_bool("B9");}  // 
  int check_level() const {return !get_bool("I2");}  // 
  
  // **
  virtual int num_turni() ;
  virtual int  inizio_turno(int t);
  virtual int  durata_turno(int t);
  virtual int numpers_turno(int t) ;

  virtual TRectype & operator=(const TRectype& rec);

  TLinea_prod(const char* cod = "") ;
  TLinea_prod(const TRectype& rec) : TUnita_produttiva (rec) {}
  TLinea_prod(const TLinea_prod& rec) : TUnita_produttiva (rec){}
  virtual ~TLinea_prod() { }
};

TImpianto  * get_impianto(const char * codice);
TLinea_prod* get_linea(const char * codice);

void find_price(const TString &tipocv, const TString &codcv, const TString &codcatven, 
  const char * tipocf, long codcf, const char * codice, const real & qta, real & price);

#endif