#pragma once
//===========================================================================//
// File:	 Raid.hpp														 //
// Project:  GameOS					                                         //
// Contents: code to submit raid bugs					  					 //
//---------------------------------------------------------------------------//
// Date			Who			Modification                                     // 
// 05/18/2000   bcrocco     Created											 //
//																			 //
//---------------------------------------------------------------------------//
// Copyright (C) 2000 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include <Sql.h>			//ODBC Header File
#include <Sqlext.h>			//ODBC Header File
#include <Sqltypes.h>		//ODBC Header File
#include <Odbcss.h>			//SQL Server driver-specific header file	

extern SQLRETURN (WINAPI* _SQLAllocHandle)(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE* OutputHandlePtr);
extern SQLRETURN (WINAPI* _SQLSetEnvAttr)(SQLHENV EnvironmentHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength);
extern SQLRETURN (WINAPI* _SQLDriverConnect)(SQLHDBC ConnectionHandle,SQLHWND WindowHandle,SQLCHAR* InConnectionString,SQLSMALLINT StringLength1,SQLCHAR* OutConnectionString,SQLSMALLINT BufferLength,SQLSMALLINT* StringLength2Ptr,SQLUSMALLINT DriverCompletion);
extern SQLRETURN (WINAPI* _SQLDisconnect)(SQLHDBC ConnectionHandle);
extern SQLRETURN (WINAPI* _SQLFreeHandle)(SQLSMALLINT HandleType,SQLHANDLE Handle);
extern SQLRETURN (WINAPI* _SQLGetDiagRec)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR* Sqlstate,SQLINTEGER* NativeErrorPtr,SQLCHAR* MessageText,SQLSMALLINT BufferLength,SQLSMALLINT* TextLengthPtr);
extern SQLRETURN (WINAPI* _SQLGetDiagField)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLSMALLINT DiagIdentifier,SQLPOINTER DiagInfoPtr,SQLSMALLINT BufferLength,SQLSMALLINT* StringLengthPtr);
extern SQLRETURN (WINAPI* _SQLBindParameter)(SQLHSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT InputOutputType,SQLSMALLINT ValueType,SQLSMALLINT ParameterType,SQLUINTEGER ColumnSize,SQLSMALLINT DecimalDigits,SQLPOINTER ParameterValuePtr,SQLINTEGER BufferLength,SQLINTEGER* StrLen_or_IndPtr);
extern SQLRETURN (WINAPI* _SQLExecDirect)(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINTEGER TextLength);
extern SQLRETURN (WINAPI* _SQLNumResultCols)(SQLHSTMT StatementHandle,SQLSMALLINT* ColumnCountPtr);
extern SQLRETURN (WINAPI* _SQLBindCol)(SQLHSTMT StatementHandle,SQLUSMALLINT ColumnNumber,SQLSMALLINT TargetType,SQLPOINTER TargetValuePtr,SQLINTEGER BufferLength,SQLINTEGER *StrLen_or_Ind);
extern SQLRETURN (WINAPI* _SQLFetch)(SQLHSTMT StatementHandle);
extern SQLRETURN (WINAPI* _SQLFreeStmt)(SQLHSTMT StatementHandle,SQLUSMALLINT Option);

#define DELANDNULL(x) {if(x != NULL){delete(x);x=NULL;}}

const int MAXBUFLEN = 2048;
const int SQLSTATELEN = 6;

enum eBugField 
{
	TITLE=1,
	STATUS,
	ASSIGNEDTO,
	ISSUETYPE,
	SEVERITY,
	PRIORITY,
	ACCESSIBILITY,
	ENVIRONMENT,
	OPENEDBY,
	OPENEDREV,
	SOURCE,
	SOURCEID,
	HOWFOUND,
	LANG,
	DESCRIPTION
};

static char* pszDefRaidFields[] = 
{
	" ",
	"Title",
	"Status",
	"AssignedTo",
	"IssueType",
	"Severity",
	"Priority",
	"Accessibility",
	"Environment",
	"OpenedBy",
	"OpenedRev",
	"Source",
	"SourceID",
	"HowFound",
	"Lang",
	"Description"
};

enum eStatus 
{
	ACTIVE,
	RESOLVED,
	CLOSED
};

static char* pszRaidStatus[] = 
{
	"Active",
	"Resolved",
	"Closed"
};

enum eIssueType
{
	CODEDEF,
	CONTENT,
	DOCBUG,
	LOC,
	OTHERISSUE,
	SPECISSUE,
	SUGGEST,
	TESTISSUE,
	WORKITEM
};

static char* pszRaidIssue[] =
{
	"Code Defect",
	"Content",
	"Doc Bug",
	"Localization",
	"Other",
	"Spec Issue",
	"Suggestion",
	"Test Issue",
	"Work Item"
};

enum eSource
{
	BETA,
	DEVELOPMENT,
	MSDEV,
	MSOTHER,
	MSTEST,
	OTHERSOURCE,
	PGM,
	PSS,
	TESTING,
	UE
};

static char* pszRaidSource[] =
{
	"Beta",
	"Development",
	"MS Developer",
	"MS Other",
	"MS Testing",
	"Other",
	"PGM",
	"PSS",
	"Testing",
	"UE"
};

enum eHowFound
{
	ACCEPTANCE,
	ADHOCDIR,
	ADHOCGEN,
	AUTOMATION,
	BETAFOUND,
	BUGBASH,
	CODEREV,
	CONFIG,
	CUSTOMER,
	PRIVRELEASE,
	REGRESSION,
	SCENARIO,
	SCRIPTS,
	SPECREV,
	TESTCASEDEV,
	TESTPASS,
	USABILITY,
	OTHERFOUND
};
	
static char* pszRaidHowFound[] =
{
	"Acceptance",
	"Ad Hoc (directed)",
	"Ad Hoc (general)",
	"Automation",
	"Beta",
	"Bug Bash",
	"Code Review",
	"Config",
	"Customer",
	"Private Release",
	"Regression",
	"Scenario",
	"Scripts",
	"Spec Review",
	"Test Case Development",
	"Test Pass",
	"Usability",
	"Other"
};

enum eYesOrNo
{
	YES,
	NO
};

static char* pszYesOrNo[] =
{
	"Yes",
	"No"
};

enum eFieldType
{
	UNINIT,
	STRINGTYPE,
	INTEGERTYPE
};

//
//
//RAIDBUG
//Default Raid fields. Should be populated and passed to CRaid::SetDefRaidFields
//
struct RAIDBUG
{
	RAIDBUG();
	char*		pszTitle;
	char*		pszAssignedTo; 
	char*		pszEnvironment;
	char*		pszOpenedBy;
	char*		pszOpenedRev;
	char*		pszSourceID;
	char*		pszLang;

	eStatus		nStatus;
	eIssueType	nIssueType;
	eYesOrNo	nAccessibility;
	eSource		nSource;
	eHowFound	nHowFound;

	int			nSeverity;
	int			nPriority;
};

//
//
//RAIDFIELD
//Key/Value pair of Column and Value to be submitted to Raid
//
class RAIDFIELD
{
	public:

		RAIDFIELD(char* pszNewColName, char* pszNewVal);
		RAIDFIELD(char* pszNewColName, int nNewVal);
		virtual ~RAIDFIELD();

		char*		pszColName;
		eFieldType  nFieldType;

		union
		{
			SQLCHAR*	pszValue;
			int		nValue;
		};

		RAIDFIELD*	pNext;

	private:
		RAIDFIELD() {;}
		RAIDFIELD(const RAIDFIELD& c) {;}
		RAIDFIELD& operator=(const RAIDFIELD& c) {;}

};	

//
//
//CODBCSQL
//Connects/Disconnects to SQLServer; Handles ODBC errors
//
class CODBCSQL
{
	public:

		CODBCSQL();
		virtual ~CODBCSQL() = 0; 

		virtual bool Open(char* pszServer,char* pszUID,char* pszPWD,char* pszDatabase);	
		virtual bool Close();
		
		char* getErrorString();
		void setErrorString(char* pszErrStr);

	protected:
	
		SQLHENV     m_henv;		
		SQLHDBC     m_hdbc;

		RETCODE		retcode;

	    char		szErrorMsg[MAXBUFLEN];
		
		virtual void errHandler(SQLSMALLINT handleType,SQLHANDLE handle,char* pszErrorOut);
	
	private:

		CODBCSQL(const CODBCSQL& c) {;}
		CODBCSQL& operator=(const CODBCSQL& c) {;}

		bool AddToError(char* dest, char* source, int* cbDest, int nMaxDest);

};

//
//
//CRaid
//Handles Raid specific tasks such as populating default bug fields and submitting bugs (Generates/Submits SQL INSERT statement)
//
class CRaid : public CODBCSQL
{
	public:

		CRaid();
		virtual ~CRaid();

		virtual bool Open(char* pszDsn);
		bool Open(char* pszServer,char* pszUID,char* pszPWD,char* pszDatabase);	
		bool Close();
		bool GetRaidRegKey(char* pszDsn,char* szSubKey,char* pszValue);

		virtual bool SetDefRaidFields(RAIDBUG& bug);
		virtual bool SetCustFields(const char* pszCustFields);
		virtual bool SetDescription(char * pszDesc);
		virtual bool Submit(OUT char* szSubmit);
		
	protected:
	
		SQLHSTMT		m_hstmt;		

	private:

		RAIDFIELD*		pFieldHead;
		SQLUSMALLINT	nNumOfAddedFields;
		
		char szRaidDb[256];
		
		bool ListAdd(RAIDFIELD& newField);
		bool SetRaidField(char* pszColumn, char* pszValue,unsigned long ulColSize = 32);
		bool SetRaidField(char* pszColumn, int	nValue);

		CRaid(const CRaid& c) {;}
		CRaid& operator=(const CRaid& c) {;}

};

//
//
//CGOSRaid
//Adds fields that exist in GOS raid database (GAMETECH2); also adds description field (and file link)
//
class CGOSRaid : public CRaid
{
	public:

		CGOSRaid();
		virtual ~CGOSRaid();

		bool SetDescription(char * pszDesc);
	private:
	
		CGOSRaid(const CGOSRaid& c) {;}
		CGOSRaid& operator=(const CGOSRaid& c) {;}

		bool WriteExceptionFile(OUT char* pszFileNameUsed);

};
		
//
//
//GetDateYYYYMMDD
//Returns the date in the form YYYYMMDD with no '/'s
//
char* GetDateYYYYMMDD();		 

//
//
//GetShortConfig
//Returns a slimmed down machine config: processor, RAM, graphics card
//
char* GetShortConfig();