/*!
  \file    DBMSrvMsg_Error.cpp
  \author  MarcW
  \ingroup error, warning and information message handling for DBM Server
  \brief   definition of a class for error messages

    ========== licence begin  GPL
    Copyright (c) 2004-2006 SAP AG

    This program 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 program 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.
    ========== licence end


*/

#include "DBM/Srv/Message/DBMSrvMsg_Error.hpp"


DBMSrvMsg_Error::DBMSrvMsg_Error()
    :DBMSrvMsg_Base(),
     SAPDBErr_MessageList()
{
}

DBMSrvMsg_Error::DBMSrvMsg_Error(
        const DBMSrvMsg_Error::ErrorID aErrorID,
        const char* const arg0,
        const char* const arg1,
        const char* const arg2,
        const char* const arg3,
        const char* const arg4,
        const char* const arg5,
        const char* const arg6,
        const char* const arg7,
        const char* const arg8,
        const char* const arg9)
        : DBMSrvMsg_Base(),
          SAPDBErr_MessageList(
                "",
                __FILE__,  //we never use it anyway...
                __LINE__,  //we never use it anyway...
                SAPDBErr_MessageList::Error,
                (MessageID) (-25000 + 158 + aErrorID),
                DBMSrvMsg_ErrorTextArray::getErrorText(aErrorID).getText(),
                (arg0?1:0)+(arg1?1:0)+(arg2?1:0)+(arg3?1:0)+(arg4?1:0)+(arg5?1:0)+(arg6?1:0)+(arg7?1:0)+(arg8?1:0)+(arg9?1:0), //the number of arguments is calculated here, but same is done within Msg_List again :(
                arg0,
                arg1,
                arg2,
                arg3,
                arg4,
                arg5,
                arg6,
                arg7,
                arg8,
                arg9) {}

DBMSrvMsg_Error DBMSrvMsg_Error::operator+ (const SAPDBErr_MessageList& otherList ) const {
    DBMSrvMsg_Error out = *this;
    out.AppendNewMessage (otherList);
    return out;
}


bool operator==(const DBMSrvMsg_Error::ErrorID& aErrid, const SAPDBErr_MessageList& aMsgList)
{
    return (aMsgList.ID() + 25000 - 158) == int(aErrid);
}

/* \TODO activate when and if Microsoft can overload operators correctly and tcn00_Error is still in use
bool operator==(const DBMSrvMsg_Error::ErrorID aErrid, const SAPDB_UInt4 aError)
{
    return (aError + 25000 - 158) == int(aErrid);
}*/

bool DBMSrvMsg_ErrorTextArray::m_IsInitialized(false);
DBMSrvMsg_ErrorText DBMSrvMsg_ErrorTextArray::m_ErrorTextArray[DBMSrvMsg_Error::LAST_ID+1];

const DBMSrvMsg_ErrorText& DBMSrvMsg_ErrorTextArray::getErrorText(
    const DBMSrvMsg_Error::ErrorID aID) {
    
    if( !m_IsInitialized ) {
        // initialize message array
        initArray();
        m_IsInitialized = true;
    }

    if(int(aID)==int(m_ErrorTextArray[aID].getErrorID()))
        return m_ErrorTextArray[aID];
    else
    {
        //if messages were not inserted in the right order (enum order) into the error text array, we must search for them
        int i;

        for(i=0; i<DBMSrvMsg_Error::LAST_ID && aID!=m_ErrorTextArray[i].getErrorID(); i++);

        return m_ErrorTextArray[i]; //if nothing better is found DBMSrvMsg_Error::LAST_ID is reported
    }
}

void DBMSrvMsg_ErrorTextArray::initArray() {

    //construct local copy of the array
    const int sizeTempArray=22;
    DBMSrvMsg_ErrorText tempArray[sizeTempArray]=
    {
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::NOBRAIN,         "ERR_NOBRAIN: I know nothing"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::NOBEER,          "ERR_NOBEER: I want to drink %s liters"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::NODBMLOGGER,     "ERR_NODBMLOGGER: DBM logger could not be initialized"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::DBISDROPPED,     "ERR_DBISDROPPED: database %s is dropped, no commands can be executed"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::IS_NO_OPTION,    "ERR_ISNOOPTION: command %s has no option %s"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::FILECHK,         "ERR_FILECHK: Error checking file %s (%s)"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::FILEDEL,         "ERR_FILEDEL: Error deleting file %s (%s)"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::SHMNOINFOFILE,   "ERR_SHMNOINFOFILE: Shared memory missing information file"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::SHMNODATAFILE,   "ERR_SHMNODATAFILE: Shared memory missing data file"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::SHMFILEPERM,     "ERR_SHMFILEPERM: Shared memory wrong permissions (at %s, %s)"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::SHMNOTAVAILABLE, "ERR_SHMNOTAVAILABLE: Shared memory not available"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::BHIST_EXT_INVALID_LINE,"ERR_BHIST_EXT_INVALID_LINE: The line '%s' is no valid line for the external backup history."),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::BHIST_EXT_OPEN,  "ERR_BHIST_EXT_OPEN: could not open external backup history file %s"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::BHIST_EXT_WRITE, "ERR_BHIST_EXT_WRITE: could not write to external backup history file %s"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::MEMORY,          "ERR_MEMORY: required memory could not be allocated from operating system"),

        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::SETENV,          "ERR_SETENV: Could not set the environment variable '%s'."),

        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::FORMAT_SEPARATORMISSING, "ERR_FORMAT_SEPARATORMISSING: String \"%s\" does not contain the expected separator '%s'"),

        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::MEFDIRTY,        "ERR_MEFDIRTY: Media file '%s' is corrupted at line %s."),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::FORMAT_DELIMISS, "ERR_FORMAT_DELIMISS: Could not find delimiter '%s' within string \"%s\""),

        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::COMM_PACKTOOSMALL, "ERR_COMM_PACKTOOSMALL: DBM communication packet of %s bytes is too small for answer"),
        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::BHIST_TOOMUCHDATA, "ERR_BHIST_TOOMUCHDATA: Backup %s|%s has too much media or external backup information"),

        DBMSrvMsg_ErrorText(DBMSrvMsg_Error::LAST_ID,         "ERR: an error occured") // :)
    };

    bool tempArraysEndReached=false;
    int  lastIDInTempArray=0;
    int  i=0,j=0;

    //copy temp array into the static member, if there is place
    for(; !tempArraysEndReached && i<DBMSrvMsg_Error::LAST_ID; i++)
    {
        m_ErrorTextArray[i]=tempArray[j];

        if(int(tempArray[j].getErrorID())==int(DBMSrvMsg_Error::LAST_ID))
        {
            tempArraysEndReached=true;
            lastIDInTempArray=j;
        }
        else
        {
            if(i==tempArray[j].getErrorID())
                j++;
        }
    }

    //fill up the static member with copies of (LAST_ID, "ERR: an error occured"), this ensures, that we don't crash,
    //if tempArray has less then LAST_ID elements due to an accident
    for(;i<DBMSrvMsg_Error::LAST_ID; i++)
        m_ErrorTextArray[i]=tempArray[lastIDInTempArray];

    //make sure that the last member of m_ErrorTextArray is (LAST_ID, "ERR: an error occured"), this ensures, that we have
    //no problem, if tempArray contains more than LAST_ID elements due to an accident
    m_ErrorTextArray[DBMSrvMsg_Error::LAST_ID]=DBMSrvMsg_ErrorText(DBMSrvMsg_Error::LAST_ID, "ERR: an error occured");
}
