#ifndef __MR2100_H
#define __MR2100_H

#include "mrplib.h"
#include "../ve/velib.h"

void print_header(TPrinter& pr);
void print_footer(TPrinter& pr);

class TMRP_internalref;
class TMRP_internalrefs;
class TMRP_docref;
class TMRP_docrefs;
class TMRP_line;

class TMRP_record : public TObject 
{
  TMRP_time _time;         // time 
  real _on_hand;           // projected on hand
  real _unsched_orders;    // unscheduled orders
  real _resched_orders;    // rescheduled orders
  real _net_requirement;   // lot-sized net requirement
  real _gross_requirement; // gross req
  real _sched_receipts;    // scheduled receipts (released )
  real _planned_orders;    // anticipated planned orders

  TMRP_docrefs *_plans;           // doc. di pianificazione
  TMRP_docrefs *_scheduls;        // doc. di pianificazione confermati
  TMRP_docrefs *_requirements;    // gross.req. da documenti esterni
  TMRP_internalrefs *_internal_req;  // gross.req. da esplosioni interne

  void add_ref(TMRP_docref * ref, TMRP_docrefs* &refs);
public:
  const real& on_hand() const { return /*_on_hand <= ZERO ?  ZERO :*/_on_hand ; }
  const real& net_requirement() const { return _net_requirement; }
  const real& resched_orders() const { return _resched_orders; }
  const real& unsched_orders() const { return _unsched_orders; }
  const real& gross_requirement() const { return _gross_requirement; }
  const real& sched_receipts() const { return _sched_receipts; }
  const real& planned_orders() const { return _planned_orders; }

  TMRP_docrefs *requirements_refs() const { return _requirements; }
  TMRP_docrefs *scheduls_refs() const     { return _scheduls; }
  TMRP_docrefs *plans_refs() const        { return _plans; }
  TMRP_internalrefs *internal_refs() const   { return _internal_req; }

  const real& set_on_hand(const real & val) { return _on_hand=val;}
  const real& set_net_req(const real & val) { return _net_requirement=val;}
  const real& add_net_req(const real & val);
  const real& add_gross_req(const real& val , TMRP_docref *ref = NULL);
  const real& add_gross_req(const real& val , TMRP_internalref *ref );
  const real& add_sched_rec(const real& val, TMRP_docref *ref = NULL);
  const real& add_planned_ord(const real& val, TMRP_docref *ref = NULL);
  const real& add_resched_ord(const real& val);
  const real& add_unsched_ord(const real& val);

  TMRP_record & operator=(const TMRP_record & a);

  const TMRP_time& time() const { return _time; }
  virtual TObject* dup() const;

  TMRP_record(const TMRP_time& t);
  virtual ~TMRP_record() { }
};

class TException : public TObject
{
  int _from, _to;
  real _q;
  const TMRP_line * _mrpline;
protected:
public :
  virtual TObject* dup() const ;

  int from() const {return _from;}
  int to() const   {return _to;}
  const real& qta() const {return _q;}
  const TMRP_line & mrpline() const {return *_mrpline;}
  TException(const TMRP_line * line, int from, int to, const real & q);
  virtual ~TException() {}
};

class TExceptions_array : public TAssoc_array
{
public :
  bool add(TException * e);
  bool add(const TException & e);
  TExceptions_array() {} 
  virtual ~TExceptions_array() {}
};


class TMRP_line : public TSortable
{
  TCodice_articolo _codart;
  TString16 _livgiac;
  TString8 _codmag;
  TString8 _codmag_coll;
  TString8 _codimp;
  TString8 _codlin;
  long _codclifor;     
  TString _da_rdoc_key;
  bool _final_product;
  int _explosion_depth;

  static TArticolo_giacenza* _articolo_giac;

protected:  
  TArray _req_per_bucket;
  
  TPointer_array _sons;
  TArray _qta_sons;

  TString _descr;

  bool is_son(const TCodice_articolo& art) const;
  void lotti_riordino(real & minimo, real & increm) const ;

public:
  TMRP_record& record(int i) const;
  TMRP_record& record(const TMRP_time& t) const;

  const TCodice_articolo& articolo() const { return _codart; }
  const TString& livgiac() const { return _livgiac; }
  const TString& codmagdep() const { return _codmag; }
  const TString& codmagdep_coll() const { return _codmag_coll; }
  const TString& codimp() const { return _codimp; }
  const TString& codlin() const { return _codlin; }
  long  codclifor() const { return _codclifor; }
  const TString& description() const { return _descr; }
  const TString& da_rdoc_key() const { return _da_rdoc_key; }

  const TString& codmag() const { return _codmag.left(3);}
  const TString& codmagaz_coll() const { return _codmag_coll.left(3); }
  const TString& coddep() const { return _codmag.mid(3); }
  const TString& coddep_coll() const { return _codmag_coll.mid(3); }
  const TString& livgiac(int l) const;
  int explosion_depth() const { return _explosion_depth; }

  virtual int compare(const TSortable& s) const;
  int first_bucket() const { return _req_per_bucket.first(); }
  int last_bucket() const { return _req_per_bucket.last(); }
  int next_bucket(int i) const { return _req_per_bucket.succ(i); }

  int add_son(const real& qta, TMRP_line* son);
  int sons() const { return _sons.items(); }
  const TMRP_line& son(int i) const { return (const TMRP_line&)_sons[i]; }
  TMRP_line& son(int i) { return (TMRP_line&)_sons[i]; }
  const real& qta_son(int i) const { return (const real&)_qta_sons[i]; }

  const real & on_hand(int i)  const 
    {return record(i).on_hand();}

  const real & gross_requirement(int i)  const 
    {return record(i).gross_requirement();}

  const real & net_requirement(int i)  const 
    {return record(i).net_requirement();}

  const real & sched_receipts(int i)  const 
    {return record(i).sched_receipts();}

  const real & planned_orders(int i)  const 
    {return record(i).planned_orders();}

  const real & resched_orders(int i)  const 
    {return record(i).resched_orders();}

  const real & unsched_orders(int i)  const 
    {return record(i).unsched_orders();}

  const TString& set_description(const TString &s) { return _descr=s; }

  const real& set_on_hand(int i, const real& val);
  const real& set_on_hand(const TMRP_time& t,  const real& val);

  const real& add_gross_req(const TMRP_time& t, const real& val, TMRP_docref *ref = NULL);
  const real& add_gross_req(const TMRP_time& t, const real& val, TMRP_internalref *ref);
  const real& add_sched_rec(const TMRP_time& t, const real& val, TMRP_docref *ref = NULL);
  const real& add_planned_ord(const TMRP_time& t, const real& val, TMRP_docref *ref = NULL);

  const real& add_net_req(const TMRP_time& t, const real& val);
  const real& add_net_req(int i, const real& val);

  const real& set_net_req(int i, const real& val);
  const real& add_resched_ord(int i, const real& val);
  const real& add_unsched_ord(int i, const real& val);
  real sizeup_net_requirement(int i, const real& val, const real& oldnet = ZERO);

  real& giacenza_attuale(real&) const;
  real& giacenza_attuale(real&, const TDate & data_attuale) const;
  real &scorta_minima(real&) const;
  real &scorta_minima(real&, const TDate & data) const;

  const TMRP_time& lead_time(int i, TMRP_time& t, bool antic = TRUE) const;

  const TMRP_time& time(int i) const { return record(i).time(); }

  virtual TObject* dup() const;
  TMRP_line & operator=(const TMRP_line & a);
  
  // gestione eccezioni
  void reset_excepts();
  bool find_ad_excepts(bool anticipi, bool posticipi, TExceptions_array &e);
  bool find_extra_excepts(bool fixed, TExceptions_array &e);
  void print_exception(int from, int to, const real &diff, int header) const;
  bool final_product() const { return _final_product; }
  void set_final_product(bool f = TRUE) { _final_product = f;}
  void set_imp_lin(const char* imp, const char* lin);
  void set_explosion_depth(int depth) { _explosion_depth = depth; }

  // capacity review

  TMRP_line(const char* art, const char* giac, 
            const char* magdep, const char* magdepc, 
            const char* imp, const char* lin, 
            long codcli, const char* da_rdoc_key);
  TMRP_line(const TMRP_line&a);
  virtual ~TMRP_line() { }
};

class TMRP_lines : public TMRP_array
{
  bool _ignore_mag;
  bool _ignore_dep;
  bool _ignore_imp;
  bool _ignore_lin;
	bool _ignore_key;

protected:
  virtual TSortable* new_obj(const TToken_string& key) const;

public:
  TMRP_line* find(const TCodice_articolo& codart, 
                  const TString& giac, const TString& mag, const TString& magc,
                  const TString& imp, const TString& lin,
                  long codcli, const char* rdoc_key, bool create = false);
  
  TMRP_line& operator[](long n) const 
  { return (TMRP_line&)find_obj(n); }

  void ignore(bool im, bool id, bool ii, bool il, bool ik)
  { _ignore_mag = im; _ignore_dep = id; _ignore_imp = ii; _ignore_lin = il;  _ignore_key = ik; }

  virtual TObject* dup() const;
  TMRP_lines & operator= (const TMRP_lines &a);

  TMRP_lines();
  TMRP_lines(const TMRP_lines &a);
  virtual ~TMRP_lines();
};

class TMRP_docref : public TObject
{ 
  TString4 _codnum;
  int _annodoc;
  long _numdoc;
  int _numrig;
  TString4 _um;
  real _qta, _prz;

protected:
  virtual TObject* dup() const;

public:
  // settaggio valori
  void set_annodoc(int anno) { _annodoc = anno; }
  void set_codnumdoc(const char* codnum) { _codnum = codnum; }
  void set_numdoc(long numdoc) { _numdoc = numdoc; }
  void set_numrig(int nr) { _numrig = nr; }
  void set_um(const char* um) { _um = um; }
  void set_qta_residua(const real& q) { _qta = q; }

  int annodoc() const { return _annodoc; }
  const TString& codnumdoc() const { return _codnum; }
  long numdoc() const { return _numdoc; }
  int  numrig() const { return _numrig; }
  const TString& um() const { return _um; }
  const real & qta_residua() const { return _qta; }
  TDate datadoc() const;
  TDate datacons() const;
  const TString& tipodoc();
  char  statodoc();

  const TRectype& get_doc() const;
  const TRectype& get_rdoc() const;

  TMRP_docref(int anno, const char* codnum, long numdoc, int nriga,
              const char* um, const real& qta, const real& prz);
};


class TMRP_docrefs : public TArray
{
public:
  TObject* dup() const;
  TMRP_docref & get_ref(int n) {return (TMRP_docref & )operator[](n);}
  TMRP_docref * get_ref_ptr(int n) {return (TMRP_docref *)objptr(n);}
};

class TMRP_internalref : public TObject
{ 
  TMRP_line * _line;
  int _bucket;
  TDate       _date; // eliminare
  TString4    _um;
  real        _qta;

public:
  virtual TObject* dup() const;
  // settaggio valori
  void set_um(const char *um) {_um = um;}
  void set_qta(const real & qta) {_qta = qta;}
  const TMRP_line * line() const {return _line;}
  int bucket() const {return _bucket;}
  const TDate & date() const {return _date;}
  const TString& um() const {return _um;}
  const real & qta() const {return _qta;}

  TMRP_internalref(TMRP_line * line, int bucket, const real & qta);
  TMRP_internalref(const TMRP_internalref &r); 
};

class TMRP_internalrefs : public TArray
{
public:
  TMRP_internalref& get_ref(int n) const {return (TMRP_internalref & )operator[](n);}
  TMRP_internalref* get_ref_ptr(int n) {return (TMRP_internalref * )objptr(n);}
};



#endif