#ifndef __DONGLE_H
#define __DONGLE_H

#ifndef _WX_DATETIME_H
#include <wx/datetime.h>
#endif

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

class TBit_array : public wxObject
{
  unsigned char* _bit;
  size_t _size;

protected:
  virtual bool ok() const;

  void resize(size_t size);
  void copy(const TBit_array& ba);
  size_t index(size_t n) const 
  { return size_t(n / 8); }
  unsigned long mask(size_t n) const 
  { return (unsigned long)(1 << (n & 0x7)); }

public:
  TBit_array(size_t size = 0);
  TBit_array(const TBit_array& ba);
  virtual ~TBit_array();

  TBit_array& operator=(const TBit_array& ba);
  bool operator[] (size_t n) const;
  TBit_array& operator |=(const TBit_array& b); 

  size_t items() const { return 8 * _size; }
  long first_one() const;
  long last_one() const;
  size_t ones() const;

  void set(size_t n);
  void reset(size_t n);
  void neg(size_t n);

  void set(size_t n, bool on) { on ? set(n) : reset(n); }
  void set();
  void reset();
};

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

  wxString _admin, _admpwd;
  
  unsigned short _serno, _max_users, _year_assist;
  unsigned short _eprom[64];
  wxDateTime _last_update;
  TBit_array _module;
  bool _dirty;

protected:
  bool already_programmed() const;              
  
  bool hardlock_login(bool test_all_dongles);                  
  bool eutron_login(bool test_all_dongles);                  
  
  bool burn_hardlock();
  bool burn_eutron();

public:        
  bool Ok() const 
  { return _hardware != _dongle_unknown && 
           _type != _no_dongle && 
           _serno != 0xFFFF; }

public:
  bool Login(bool test_all_dongles = false);
  bool Logout();
  bool Connected();

  unsigned short Number() const { return _serno; }
  unsigned short MaxUsers() const { return _max_users; }
  unsigned short YearAssist() const { return _year_assist; }
  
  void garble(unsigned short* data) const;

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

  TDongleType type() const { return _type; }
  
  bool Active(size_t module) const { return _module[module]; }
  void Activate(size_t module, bool on = TRUE) { _module.set(module, on); _dirty = TRUE; }
  void Deactivate(size_t module) { Activate(module, FALSE); }
  void set_max_users(unsigned short u) { _max_users = u; _dirty = TRUE; }
  void set_year_assist(unsigned short y) { _year_assist = y; _dirty = TRUE; }
  const wxDateTime& last_update() const { return _last_update; }
  
  bool dirty() const { return _dirty; }
  bool Burn();
  
  TDongleHardware hardware() const { return _hardware; }
  
  TDongle();
  virtual ~TDongle();
};

long date2julian(const wxDateTime& date);

#endif