/*
 * Softcam plugin to VDR (C++)
 *
 * This code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 */

#ifndef ___DATA_H
#define ___DATA_H

#include <vdr/tools.h>
//#include <vdr/thread.h>

class cLoaders;
class cPlainKeys;

// ----------------------------------------------------------------

class cFileMap : public cListObject {
private:
  char *filename;
  bool rw;
  FILE* fptr;
  //
  int fd, len, count;
  unsigned char *addr;
  bool failed;
  //
  void Clean(void);
public:
  cFileMap(const char *Filename, bool Rw);
  ~cFileMap();
  bool Map(void);
  bool Unmap(void);
  void Sync(void);
  int Size(void) { return len; }
  unsigned char *Addr(void) { return addr; }
  bool IsFileMap(const char *Name, bool Rw);
  };

// ----------------------------------------------------------------

class cFileMaps : public cList<cFileMap> {
private:
  char *cfgDir;
public:
  cFileMaps(void);
  ~cFileMaps();
  void SetCfgDir(const char *CfgDir);
  cFileMap *GetFileMap(const char *name, const char *domain, bool rw);
  };

extern cFileMaps filemaps;

// ---------------------------------------------------------------

class cLoader {
friend class cLoaders;
private:
  cLoader *next;
  bool modified;
  const char *id;
protected:
  void Modified(bool mod=true) { modified=mod; }
public:
  cLoader(const char *Id);
  virtual bool ParseLine(char *line, bool fromCache)=0;
  virtual bool Save(FILE *f)=0;
  bool IsModified(void) { return modified; }
  const char *Id(void) { return id; }
  };

// ----------------------------------------------------------------

class cLoaders {
friend class cLoader;
private:
  static cLoader *first;
/*  static cMutex lock;*/
  static char *cacheFile;
  //
  static void Register(cLoader *ld);
  static cLoader *FindLoader(const char *id);
  static bool IsModified(void);
public:
  static void LoadCache(const char *cfgdir);
  static void SaveCache(void);
  };

// ----------------------------------------------------------------

class cEcmInfo : public cListObject {
private:
  bool cached, failed;
  //
  void Setup(void);
protected:
  bool needData;
  int dataLen;
  unsigned char *data;
  //
  void ClearData(void);
public:
  char *name;
  int ecm_pid;
  int caId, provId;
  int prgId, source, transponder;
  //
  cEcmInfo(void);
  cEcmInfo(cEcmInfo *e);
  cEcmInfo(const char *Name, int Pid, int CaId, int ProvId);
  ~cEcmInfo();
  void Update(cEcmInfo *e);
  void SetSource(int PrgId, int Source, int Transponder);
  bool AddData(const unsigned char *Data, int DataLen);
  void SetName(const char *Name);
  const unsigned char *Data(void) const { return data; }
  bool NeedData(void) const { return needData; }
  void Fail(bool st) { failed=st; }
  bool Failed(void) const { return failed; }
  bool Cached(void) const { return cached; }
  };

// ----------------------------------------------------------------

class cEcmData : public cEcmInfo {
private:
  bool del;
public:
  cEcmData(void);
  cEcmData(cEcmInfo *e);
  bool Save(FILE *f);
  bool Parse(const char *buf);
  void Delete(void) { del=true; }
  bool IsDeleted(void) { return del; }
  };

// ----------------------------------------------------------------

class cEcmCache : public cLoader/*, cMutex*/, cList<cEcmData> {
private:
  cEcmData *Exists(cEcmInfo *e);
public:
  cEcmCache(void);
  void Load(void);
  void New(cEcmInfo *e);
  int GetCached(cList<cEcmInfo> *list, int PrgId, int Source, int Transponder);
  void Delete(cEcmInfo *e);
  virtual bool Save(FILE *f);
  virtual bool ParseLine(char *line, bool fromCache);
  };

extern cEcmCache ecmcache;

// ----------------------------------------------------------------

class cPlainKey : public cListObject {
friend class cPlainKeys;
private:
  bool au, del, super;
protected:
  void SetInvalid(void) { del=true; }
  void SetAuto(void) { au=true; }
  bool IsAuto(void) { return au; }
  bool IsInvalid(void) { return del; }
  bool CanSupersede(void) { return super; }
  virtual bool SetKey(void *Key, int Keylen)=0;
  virtual bool SetKeyFromBin(void *Key, int Keylen) { return SetKey(Key,Keylen); }
public:
  int type, id, keynr;
  //
  cPlainKey(bool CanSupersede);
  virtual bool Parse( char *line)=0;
  virtual bool Save(FILE *f)=0;
  virtual char *Print(void)=0;
  virtual bool Cmp(void *Key, int Keylen)=0;
  virtual void Get(void *mem)=0;
  virtual int Size(void)=0;
  bool Set(int Type, int Id, int Keynr, void *Key, int Keylen);
  };

// ----------------------------------------------------------------

class cPlainKeyType {
friend class cPlainKeys;
private:
  int type;
  cPlainKeyType *next;
public:
  cPlainKeyType(int Type, bool Super);
  virtual cPlainKey *Create(void)=0;
  };

// ----------------------------------------------------------------

template<class PKT, int KT, bool SUP=true> class cPlainKeyTypeReg : public cPlainKeyType {
public:
  cPlainKeyTypeReg(void):cPlainKeyType(KT,SUP) {}
  virtual cPlainKey *Create(void) { return new PKT(SUP); }
  };

// ----------------------------------------------------------------

class cPlainKeys : public cLoader,/* cMutex,*/ cList<cPlainKey> {
friend class cPlainKeyType;
private:
  static cPlainKeyType *first;
  //
  static void Register(cPlainKeyType *pkt, bool Super);
  cPlainKey *NewFromType(int type);
  bool Supersede(cPlainKey *nk, bool log);
public:
  cPlainKeys(void);
  bool Load(const char *cfgdir);
  virtual bool Save(FILE *f);
  virtual bool ParseLine(char *line, bool Au=true);
  cPlainKey *FindKey(int Type, int Id, int Keynr, cPlainKey *key=0);
  bool NewKey(int Type, int Id, int Keynr, void *Key, int Keylen);
  };

extern cPlainKeys keys;

#endif //___DATA_H
