#ifndef __DONGLE_H
#define __DONGLE_H

#ifndef __DATE_H
#include <date.h>
#endif

#ifndef __STRINGS_H
#include <strings.h>
#endif

enum TDongleHardware { _dongle_unknown, _dongle_hardlock, _dongle_eutron, _dongle_network };
enum TDongleType { _no_dongle, _user_dongle, _developer_dongle, _aga_dongle };
enum { MAX_DONGLE_ASSIST = 8 };

class TDongle : public TObject
{     
  TDongleHardware _hardware;
  TDongleType _type;

  TString _admin, _admpwd, _reseller, _product, _shortname;
  
  word _serno, _max_users, _year_assist;
  word _eprom[64];
  TDate _last_update;
  TBit_array _module;
  TBit_array _shown;
  bool _dirty;

  TDate _last_assist;
  unsigned long _assist[MAX_DONGLE_ASSIST]; // Centesimi di Euro pre-pagati

  TString_array _info; // Informazioni sui moduli
  
protected:
  bool already_programmed() const;              
  void set_developer_permissions();
  bool hardlock_login(bool test_all_dongles);                  
  bool eutron_login(bool test_all_dongles);                  
  bool network_login(bool test_all_dongles);                  
  
  bool burn_hardlock();
  bool burn_eutron();

  int can_try_server() const;
  const TString_array& info() const; // Array di coppie modulo|descrizione
  
public:        // TObject
  virtual bool ok() const 
  { return _hardware != _dongle_unknown && 
           _type != _no_dongle && 
           _serno != 0xFFFF; }

public:
  bool login(bool test_all_dongles = false);                  
  bool logout();

  word number() const { return _serno; }
  word max_users() const { return _max_users; }
  word year_assist() const { return _year_assist; }
  
  void garble(word* data) const;

  // Solo per un po' di tempo, poi diverranno protected (servono a ba1500 old style)
  bool read_words(word reg, word len, word *data) const;
  bool write_words(word reg, word len, word *data) const;

  TDongleType type() const { return _type; }
  
  bool active(word module) const;
  bool activate(word module, bool on = true);
  void deactivate(word module) { activate(module, false); }
  void set_max_users(word u) { _max_users = u; _dirty = true; }
  void set_year_assist(word y) { _year_assist = y; _dirty = true; }
  const TDate& last_update() const { return _last_update; }
  
  bool dirty() const { return _dirty; }
  bool burn();
  
  TDongleHardware hardware() const { return _hardware; }
  bool local() const { return _hardware == _dongle_hardlock || _hardware == _dongle_eutron; }
  bool network() const { return _hardware == _dongle_network; }
  
  real residual_assist(int index, bool lire) const;
  bool can_require_assist(int index) const;
  bool require_assist(int index, real imp, bool lire);
  bool pay_assist(int index, real imp, bool lire);

  const TString& administrator(TString* pwd = NULL) const;
  const TString& reseller() const;
  const TString& product() const;
  const TString& shortname() const;

  word module_name2code(const char* module) const;    // Converte un nome di due lettere in numero
  const TString& module_code2name(word module) const; // ... e viceversa
  const TString& module_code2desc(word module) const; // Descrizione estesa del modulo
  const TString& module_name2desc(const char* mod) const; // Converte un nome di due lettere in descrizione

  bool shown(word module) const;                      // Stabilisce se un modulo e' visibile in installazione
  bool hidden(word module) const { return !shown(module); } // Modulo invisibile

  TDongle();
  virtual ~TDongle();
};

TDongle& dongle();
bool destroy_dongle();

#endif