/***************************************************************************
                          charactersinkodbc.cpp  -  description
                             -------------------
    begin                : Mon Dec 9 2002
    copyright            : (C) 2002 by Andrew Dunn
    email                : andrew.dunn@futureroute.co.uk
 ***************************************************************************/


#include "charactersinkodbc.h"

CharacterSinkODBC::CharacterSinkODBC(){}
/**
  *CharacterSinkODBC - Construct and Initialise the Database Connection
  */
CharacterSinkODBC::CharacterSinkODBC(char *DSNString){
    this->DSN = DSNString;
    this->norecordsinserted = 0;
    this->SQLError(initialise());
}
/**
  *~CharacterSinkODBC - Destructa nd disconnect from Database
  */
CharacterSinkODBC::~CharacterSinkODBC(){
    cout << "<Destructing>..." ;
    this->SQLError(dbDisconnect());
}

/**
  *insertNextCharacter - Insert a new character into Database
  */
bool CharacterSinkODBC::putNextCharacter(char *characterstring){

    int temp = 0;

    SQLAllocHandle( SQL_HANDLE_STMT, hDbc ,&hStmt);

    SQLBindParameter(hStmt,                     //StatementHandle
                     1,                         //ParameterNumber
                     SQL_PARAM_OUTPUT,          //InputOutputType
                     SQL_INTEGER,               //ValueType INput
                     SQL_INTEGER,               //ParameterType Actual Table Type
                     0,                         //ColumnSize
                     0,                         //DecimalDigits
                     &temp,                     //ParameterValuePtr
                     sizeof(int),               //BufferLength
                     NULL);                     //StrLen_or_IndPtr

    
    SQLBindParameter(hStmt,                     //StatementHandle
                     2,                         //ParameterNumber
                     SQL_PARAM_INPUT,           //InputOutputType
                     SQL_C_CHAR,                //ValueType Input
                     SQL_VARCHAR,               //ParameterType Actual Table Type
                     4000,                      //ColumnSize
                     0,                         //DecimalDigits
                     (SQLCHAR *)characterstring,//ParameterValuePtr
                     sizeof(characterstring),   //BufferLength
                     NULL);                     //StrLen_or_IndPtr

                  
    ret = SQLExecDirect(hStmt,
                        (SQLCHAR*) "{? = CALL [insertPrototypeCharacter](?)}",
                        SQL_NTS );
    SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
    
    if(!SQL_SUCCEEDED(this->ret)){
        SQLError(this->ret);
        return false;
    }
    else{
        rowNum.push_back(temp);
        norecordsinserted++;
        
        return true;
    }
}


/**
  *reset - Reset datasource to begining
  *        Remove all inserted Records
  */
bool CharacterSinkODBC::reset(){
      
    for(unsigned int i = 0; i < rowNum.size();  i++){
        SQLAllocHandle( SQL_HANDLE_STMT, hDbc ,&hStmt);
        SQLPrepare(hStmt,(SQLCHAR*)"DELETE FROM [character] WHERE characterID = ?", SQL_NTS);

        int val = rowNum[i];
        cout << "Bind Vector Contents " << i << " "<< rowNum[i] << " " ;
        ret = SQLBindParameter(hStmt,                  //StatementHandle
                               1,                      //ParameterNumber
                               SQL_PARAM_INPUT,        //InputOutputType
                               SQL_INTEGER,            //ValueType INput
                               SQL_INTEGER,            //ParameterType Actual Table Type
                               0,                      //ColumnSize
                               NULL,                   //DecimalDigits
                               &val,              //ParameterValuePtr
                               sizeof(val),            //BufferLength
                               SQL_NTS);                  //StrLen_or_IndPtr
        SQLError(ret);
        ret = SQLExecute(hStmt);
        
        cout << "Delete OP "; SQLError(ret);
        if(ret == SQL_SUCCESS){
            norecordsinserted--;
        }
        SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
        
    }
    
    if(norecordsinserted == 0){
        cout << "All Records Deleted" << endl;
        return true;
    }
    else{
        cout << "Oh Dear Records Deleted" << endl;
        return false;
    }
}
/**
  *dataSource - Return the name of the datasource
  */
char *CharacterSinkODBC::dataSource(){return DSN;}

/**
  *norecordsInserted - Return the Number of Records Inserted during this session
  */    
int CharacterSinkODBC::norecordsInserted(){return norecordsinserted;}

/**
  *dbConnect - Connect to DSN
  */
SQLRETURN CharacterSinkODBC::dbConnect(){
    return SQLDriverConnect(hDbc, NULL, (unsigned char *) DSN, SQL_NTS, text,256, &len, SQL_DRIVER_COMPLETE);
}

/**
  *dbDisconnect - Disconnect from DataSource
  */
SQLRETURN CharacterSinkODBC::dbDisconnect(){

    SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
    ret = SQLDisconnect( hDbc );
    SQLFreeHandle( SQL_HANDLE_DBC, hDbc );
    SQLFreeHandle( SQL_HANDLE_ENV, hEnv );
    return ret;
}

/**
  *initialise() - Initialise Environment fr ODB Connection
  */
SQLRETURN CharacterSinkODBC::initialise(){
    cout << "<Initialise>...";
    // Alloacte Envirnment
    ret = SQLAllocHandle( SQL_HANDLE_ENV, 0, &hEnv);
    if(!SQL_SUCCEEDED(ret)) cout << "ERROR:- Unable to Alloacte Environment" << endl;

    //Set ODBC Behaviour
    SQLSetEnvAttr( hEnv, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC2, 0);
    ret = SQLAllocHandle( SQL_HANDLE_DBC, hEnv, &hDbc );
    if(!SQL_SUCCEEDED(ret)) cout << "ERROR:- Unable to Allocate Connection Handle" << endl;
    
    //Call for Connection
    SQLError(dbConnect());

    //Allocate Statement Handle and exit
    return SQLAllocHandle( SQL_HANDLE_STMT, hDbc ,&hStmt);
}

/**
  *SQLError - Some small explanation of SQL Messages
  */
void CharacterSinkODBC::SQLError(SQLRETURN returnvalue){
    switch(returnvalue){
        case SQL_SUCCESS:
            cout << "SQL SUCCESS" << endl;
            break;
        case SQL_SUCCESS_WITH_INFO:
            cout << "SUCCESS WITH MORE INFO" << endl;
            break;
        case SQL_NEED_DATA:
            cout << "SQL NEED DATA" << endl;
            break;
        case SQL_STILL_EXECUTING:
            cout << "SQL STILL EXECUTING" << endl;
            break;
        case SQL_ERROR:
            cout << "SQL ERROR" << endl;
            break;
        case SQL_NO_DATA:
            cout << "SQL NO DATA" << endl;
            break;
        case SQL_INVALID_HANDLE:
            cout << "SQL INVALID HANDLE" << endl;
            break;
        default:
            cout << "ERROR NOT DEFINED............." << endl;
            break;
    }
    return;   
}



