/****************************************************************************\
 *
 *   PICS.H --Structures for holding pics information
 *
 *   Created:   Jason Thomas
 *   Updated:   Ann McCurdy
 *   
\****************************************************************************/

#ifndef _PICS_H_
#define _PICS_H_

/*Includes---------------------------------------------------------*/
#include <npassert.h>
#include "array.h"
#include "resource.h"
#include "msluglob.h"
#include <ratings.h>

extern HKEY CreateRegKeyNT(LPCSTR pszKey);
extern BOOL RunningOnNT(void);

extern char PicsDelimChar;

#define PICS_FILE_BUF_LEN   20000
#define PICS_STRING_BUF_LEN  1000

#define P_INFINITY           9999
#define N_INFINITY          -9999

/*Simple PICS types------------------------------------------------*/

class ETN
{
    private:
        int r;
        BOOL m_fInit;
    public:
        ETN() { m_fInit = FALSE; }

        void Init() { m_fInit = TRUE; }
        void UnInit() { m_fInit = FALSE; }
        BOOL fIsInit() { return m_fInit; }

#ifdef DEBUG
        void  Set(int rIn);
        int Get();
#else
        void  Set(int rIn) { Init(); r = rIn; }
        int Get() { return r; }
#endif

        ETN*  Duplicate();
};

const UINT ETB_VALUE = 0x01;
const UINT ETB_ISINIT = 0x02;
class ETB
{
    private:
        UINT m_nFlags;
    public:
        ETB() { m_nFlags = 0; }

#ifdef DEBUG
        BOOL Get();
        void Set(BOOL b);
#else
        BOOL Get() { return m_nFlags & ETB_VALUE; }
        void Set(BOOL b) { m_nFlags = ETB_ISINIT | (b ? ETB_VALUE : 0); }
#endif

        ETB   *Duplicate();
        BOOL fIsInit() { return m_nFlags & ETB_ISINIT; }
};

class ETS
{
    private:
        char *pc;
    public:
        ETS() { pc = NULL; }
        ~ETS();
#ifdef DEBUG
        char* Get();
#else
        char *Get() { return pc; }
#endif
        void  Set(const char *pIn);
        ETS*  Duplicate();
        void  SetTo(char *pIn);

        BOOL fIsInit() { return pc != NULL; }
};

extern UINT EtBoolRegRead(ETB &etb, HKEY hKey, char *pKeyWord);
extern UINT EtBoolRegWrite(ETB &etb, HKEY hKey, char *pKeyWord);
extern UINT EtStringRegRead(ETS &ets, HKEY hKey, char *pKeyWord);
extern UINT EtStringRegWrite(ETS &ets, HKEY hKey, char *pKeyWord);
extern UINT EtNumRegRead(ETN &etn, HKEY hKey, char *pKeyWord);
extern UINT EtNumRegWrite(ETN &etn, HKEY hKey, char *pKeyWord);


/*Complex PICS types-----------------------------------------------*/


enum RatObjectID
{
    ROID_INVALID,           /* dummy entry for terminating arrays */
    ROID_PICSDOCUMENT,      /* value representing the entire document (i.e., no token) */
    ROID_PICSVERSION,
    ROID_RATINGSYSTEM,
    ROID_RATINGSERVICE,
    ROID_RATINGBUREAU,
    ROID_BUREAUREQUIRED,
    ROID_CATEGORY,
    ROID_TRANSMITAS,
    ROID_LABEL,
    ROID_VALUE,
    ROID_DEFAULT,
    ROID_DESCRIPTION,
    ROID_EXTENSION,
    ROID_MANDATORY,
    ROID_OPTIONAL,
    ROID_ICON,
    ROID_INTEGER,
    ROID_LABELONLY,
    ROID_MAX,
    ROID_MIN,
    ROID_MULTIVALUE,
    ROID_NAME,
    ROID_UNORDERED
};

enum PICSRulesObjectID
{
    PROID_INVALID,                  /* dummy entry for terminating arrays */
    PROID_PICSVERSION,              /* for holding the PICSRules version ID */
    
    PROID_POLICY,                   /* for the Policy class */
        PROID_EXPLANATION,
        PROID_REJECTBYURL,
        PROID_ACCEPTBYURL,
        PROID_REJECTIF,
        PROID_ACCEPTIF,
        PROID_ACCEPTUNLESS,
        PROID_REJECTUNLESS,
    PROID_NAME,                     /* for the name class */
        PROID_RULENAME,
        PROID_DESCRIPTION,
    PROID_SOURCE,                   /* for the source class */
        PROID_SOURCEURL,
        PROID_CREATIONTOOL,
        PROID_AUTHOR,
        PROID_LASTMODIFIED,
    PROID_SERVICEINFO,              /* for the serviceinfo class */
        PROID_SINAME,
        PROID_SHORTNAME,
        PROID_BUREAUURL,
        PROID_USEEMBEDDED,
        PROID_RATFILE,
        PROID_BUREAUUNAVAILABLE,
    PROID_OPTEXTENSION,             /* for the optextension class */
        PROID_EXTENSIONNAME,
      //PROID_SHORTNAME,
    PROID_REQEXTENSION,
      //PROID_EXTENSIONNAME,
      //PROID_SHORTNAME,
    PROID_EXTENSION,

    PROID_POLICYDEFAULT,
    PROID_NAMEDEFAULT,
    PROID_SOURCEDEFAULT,
    PROID_SERVICEINFODEFAULT,
    PROID_OPTEXTENSIONDEFAULT,
    PROID_REQEXTENSIONDEFAULT
};

/* define some error codes */
const HRESULT RAT_E_BASE = 0x80050000;                  /* just a guess at a free area for internal use */
const HRESULT RAT_E_EXPECTEDLEFT    = RAT_E_BASE + 1;   /* expected left paren */
const HRESULT RAT_E_EXPECTEDRIGHT   = RAT_E_BASE + 2;   /* expected right paren */
const HRESULT RAT_E_EXPECTEDTOKEN   = RAT_E_BASE + 3;   /* expected unquoted token */
const HRESULT RAT_E_EXPECTEDSTRING  = RAT_E_BASE + 4;   /* expected quoted string */
const HRESULT RAT_E_EXPECTEDNUMBER  = RAT_E_BASE + 5;   /* expected number */
const HRESULT RAT_E_EXPECTEDBOOL    = RAT_E_BASE + 6;   /* expected boolean */
const HRESULT RAT_E_DUPLICATEITEM   = RAT_E_BASE + 7;   /* AO_SINGLE item appeared twice */
const HRESULT RAT_E_MISSINGITEM     = RAT_E_BASE + 8;   /* AO_MANDATORY item not found */
const HRESULT RAT_E_UNKNOWNITEM     = RAT_E_BASE + 9;   /* unrecognized token */
const HRESULT RAT_E_UNKNOWNMANDATORY= RAT_E_BASE + 10;  /* unrecognized mandatory extension */
const HRESULT RAT_E_EXPECTEDEND     = RAT_E_BASE + 11;  /* expected end of file */

/* echo for PICSRules with different names for clarity */
const HRESULT PICSRULES_E_BASE              = 0x80050000;       /* just a guess at a free area for internal use */
const HRESULT PICSRULES_E_EXPECTEDLEFT      = RAT_E_BASE + 1;   /* expected left paren */
const HRESULT PICSRULES_E_EXPECTEDRIGHT     = RAT_E_BASE + 2;   /* expected right paren */
const HRESULT PICSRULES_E_EXPECTEDTOKEN     = RAT_E_BASE + 3;   /* expected unquoted token */
const HRESULT PICSRULES_E_EXPECTEDSTRING    = RAT_E_BASE + 4;   /* expected quoted string */
const HRESULT PICSRULES_E_EXPECTEDNUMBER    = RAT_E_BASE + 5;   /* expected number */
const HRESULT PICSRULES_E_EXPECTEDBOOL      = RAT_E_BASE + 6;   /* expected boolean */
const HRESULT PICSRULES_E_DUPLICATEITEM     = RAT_E_BASE + 7;   /* AO_SINGLE item appeared twice */
const HRESULT PICSRULES_E_MISSINGITEM       = RAT_E_BASE + 8;   /* AO_MANDATORY item not found */
const HRESULT PICSRULES_E_UNKNOWNITEM       = RAT_E_BASE + 9;   /* unrecognized token */
const HRESULT PICSRULES_E_UNKNOWNMANDATORY  = RAT_E_BASE + 10;  /* unrecognized mandatory extension */
const HRESULT PICSRULES_E_EXPECTEDEND       = RAT_E_BASE + 11;  /* expected end of file */
const HRESULT PICSRULES_E_SERVICEUNDEFINED  = RAT_E_BASE + 12;  /* a service referenced is undefined */
const HRESULT PICSRULES_E_REQEXTENSIONUSED  = RAT_E_BASE + 13;  /* an unknown required extension was used */
const HRESULT PICSRULES_E_VERSION           = RAT_E_BASE + 14;  /* a non-support version was presented */

/* A RatObjectHandler parses the contents of a parenthesized object and
 * spits out a binary representation of that data, suitable for passing
 * to an object's AddItem function.  It does not consume the ')' which
 * closes the object.
 */
class RatFileParser;
typedef HRESULT (*RatObjectHandler)(LPSTR *ppszIn, LPVOID *ppOut, RatFileParser *pParser);

class PICSRulesFileParser;
typedef HRESULT (*PICSRulesObjectHandler)(LPSTR *ppszIn, LPVOID *ppOut, PICSRulesFileParser *pParser);

class PicsCategory;

class PicsObjectBase
{
public:
    virtual HRESULT AddItem(RatObjectID roid, LPVOID pData) = 0;
    virtual HRESULT InitializeMyDefaults(PicsCategory *pCategory) = 0;
};

class PICSRulesObjectBase
{
public:
    virtual HRESULT AddItem(PICSRulesObjectID proid, LPVOID pData) = 0;
    virtual HRESULT InitializeMyDefaults() = 0;
};

const DWORD AO_SINGLE = 0x01;
const DWORD AO_SEEN = 0x02;
const DWORD AO_MANDATORY = 0x04;

struct AllowableOption
{
    RatObjectID roid;
    DWORD fdwOptions;
};

struct PICSRulesAllowableOption
{
    PICSRulesObjectID roid;
    DWORD fdwOptions;
};

class PicsEnum : public PicsObjectBase
{
    private:
    public:
        ETS etstrName, etstrIcon, etstrDesc;
        ETN etnValue;

        PicsEnum();
        ~PicsEnum();
//        char* Parse(char *pStreamIn);

        HRESULT AddItem(RatObjectID roid, LPVOID pData);
        HRESULT InitializeMyDefaults(PicsCategory *pCategory);
};

class PicsRatingSystem;

class PicsCategory : public PicsObjectBase
{
    private:
    public:
        array<PicsCategory*> arrpPC;
        array<PicsEnum*>     arrpPE;
        ETS   etstrTransmitAs, etstrName, etstrIcon, etstrDesc;
        ETN   etnMin,   etnMax;
        ETB   etfMulti, etfInteger, etfLabelled, etfUnordered;
        PicsRatingSystem *pPRS;

        PicsCategory();
        ~PicsCategory();
//        char* Parse(char *pStreamIn, char *pBaseName, PicsCategory *pPCparent);
        void FixupLimits();
        void SetParents(PicsRatingSystem *pOwner);

        HRESULT AddItem(RatObjectID roid, LPVOID pData);
        HRESULT InitializeMyDefaults(PicsCategory *pCategory);
};


class PicsDefault : public PicsObjectBase
{
public:
    ETB etfInteger, etfLabelled, etfMulti, etfUnordered;
    ETN etnMax, etnMin;

    PicsDefault();
    ~PicsDefault();

    HRESULT AddItem(RatObjectID roid, LPVOID pData);
    HRESULT InitializeMyDefaults(PicsCategory *pCategory);
};


class PicsExtension : public PicsObjectBase
{
public:
    LPSTR m_pszRatingBureau;

    PicsExtension();
    ~PicsExtension();

    HRESULT AddItem(RatObjectID roid, LPVOID pData);
    HRESULT InitializeMyDefaults(PicsCategory *pCategory);
};


class PicsRatingSystem : public PicsObjectBase
{
    private:
    public:
        array<PicsCategory*> arrpPC;
        ETS                  etstrFile, etstrName, etstrIcon, etstrDesc, 
                             etstrRatingService, etstrRatingSystem, etstrRatingBureau;
        ETN                  etnPicsVersion;
        ETB                  etbBureauRequired;
        PicsDefault *        m_pDefaultOptions;
        DWORD                dwFlags;
        UINT                 nErrLine;

        PicsRatingSystem();
        ~PicsRatingSystem();
        HRESULT Parse(LPCSTR pszFile, LPSTR pStreamIn);

        HRESULT AddItem(RatObjectID roid, LPVOID pData);
        HRESULT InitializeMyDefaults(PicsCategory *pCategory);
        void ReportError(HRESULT hres);
};

/* bit values for PicsRatingSystem::dwFlags */
const DWORD PRS_ISVALID = 0x01;         /* this rating system was loaded successfully */
const DWORD PRS_WASINVALID = 0x02;      /* was invalid last time we tried to load it */

/* echo for PICSRules with different names for clarity */
#define PRRS_ISVALID        PRS_ISVALID;
#define PRRS_WASINVALID     PRS_WASINVALID;

class UserRating : public NLS_STR
{
public:
    INT m_nValue;
    UserRating *m_pNext;
    PicsCategory *m_pPC;

    UserRating();
    UserRating(UserRating *pCopyFrom);
    ~UserRating();

    UserRating *Duplicate(void);
    void SetName(LPCSTR pszName) { *(NLS_STR *)this = pszName; }
};


class UserRatingSystem : public NLS_STR
{
public:
    UserRating *m_pRatingList;
    UserRatingSystem *m_pNext;
    PicsRatingSystem *m_pPRS;

    UserRatingSystem();
    UserRatingSystem(UserRatingSystem *pCopyFrom);
    ~UserRatingSystem();

    UserRating *FindRating(LPCSTR pszTransmitName);
    UINT AddRating(UserRating *pRating);
    UINT ReadFromRegistry(HKEY hkeyProvider);
    UINT WriteToRegistry(HKEY hkey);

    UserRatingSystem *Duplicate(void);
    void SetName(LPCSTR pszName) { *(NLS_STR *)this = pszName; }
};


UserRatingSystem *DuplicateRatingSystemList(UserRatingSystem *pOld);
void DestroyRatingSystemList(UserRatingSystem *pList);
UserRatingSystem *FindRatingSystem(UserRatingSystem *pList, LPCSTR pszName);


class PicsUser{
private:
public:
    NLS_STR nlsUsername; 
    BOOL fAllowUnknowns, fPleaseMom, fEnabled;
    UserRatingSystem *m_pRatingSystems;

    PicsUser();
    ~PicsUser();

    UserRatingSystem *FindRatingSystem(LPCSTR pszSystemName) { return ::FindRatingSystem(m_pRatingSystems, pszSystemName); }
    UINT AddRatingSystem(UserRatingSystem *pRatingSystem);
    BOOL NewInstall();
    UINT ReadFromRegistry(HKEY hkey, char *pszUserName);
    UINT WriteToRegistry(HKEY hkey);
};


PicsUser *GetUserObject(LPCSTR pszUsername=NULL);


extern long GetStateCounter();

class PicsRatingSystemInfo
{
    public:
        array<PicsRatingSystem*> arrpPRS;
        PicsUser *               pUserObject;
        BOOL                     fRatingInstalled;
        ETS                      etstrRatingBureau;
        long                     nInfoRev;
        BOOL                     fStoreInRegistry;
        BOOL                     fSettingsValid;
        PSTR                     lpszFileName;

        PicsRatingSystemInfo() { lpszFileName=NULL; nInfoRev = ::GetStateCounter(); };
        ~PicsRatingSystemInfo();

        BOOL Init();
        BOOL FreshInstall();
        void SaveRatingSystemInfo();
        BOOL LoadProviderFiles(HKEY hKey);

    protected:
        HKEY    GetUserProfileKey( void );
};

extern PicsRatingSystemInfo *gPRSI;

void CheckGlobalInfoRev(void);


char* EtStringParse(ETS &ets, char *pIn, const char *pKeyWord, BOOL fParen);
char* EtLabelParse(char *pIn, const char *pszLongName, const char *pszShortName);
char* EtRatingParse(ETN &etn, ETS &ets, char *pInStream);

int  MyMessageBox(HWND hwnd, UINT uText, UINT uTitle, UINT uType);
int  MyMessageBox(HWND hwnd, UINT uText, UINT uText2, UINT uTitle, UINT uType);
int  MyMessageBox(HWND hwnd, LPCSTR pszText, UINT uTitle, UINT uType);
char *NonWhite(char *pIn);
BOOL MyAtoi(char *pIn, int *i);
LONG MyRegDeleteKey(HKEY hkey,LPCSTR pszSubkey);
HRESULT LoadRatingSystem(LPCSTR pszFilename, PicsRatingSystem **pprsOut);
INT_PTR DoProviderDialog(HWND hDlg, PicsRatingSystemInfo *pPRSI);

void DeleteUserSettings(PicsRatingSystem *pPRS);
void CheckUserSettings(PicsRatingSystem *pPRS);

//
// Declarations for Custom
//
extern g_fIsRunningUnderCustom;

struct CustomRatingHelper
{
    CustomRatingHelper();
    ~CustomRatingHelper();

    HMODULE hLibrary;
    CLSID clsid;
    CustomRatingHelper* pNextHelper;
    DWORD dwSort;
};

/*Pics Tree Dialog Stuff------------------------------------------------------*/
struct PRSD
{
    PicsRatingSystemInfo *pPRSI;
    PicsUser             *pPU;
    UserRatingSystem     *pTempRatings;
    HWND                  hwndBitmapCategory;
    HWND                  hwndBitmapLabel;
    BOOL                  fNewProviders;
};

enum TreeNodeEnum{tneGeneral, tneAccessList, tneRatingSystemRoot, tneRatingSystemInfo, tneRatingSystemNode, tneNone};

struct TreeNode{
    TreeNodeEnum  tne;
    void         *pData;

    TreeNode(){}
    TreeNode(TreeNodeEnum tneInit, void* pDataInit){tne=tneInit;pData=pDataInit;}
};

PicsRatingSystem *FindInstalledRatingSystem(LPCSTR pszRatingService);
PicsCategory *FindInstalledCategory(array<PicsCategory *>&arrpPC, LPCSTR pszName);

HRESULT Ansi2Unicode(LPWSTR *pdest, LPCSTR src);

#endif