/**
 * Requires:
 *   - callFailureEvent
 *   - addCallData
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_XML::callFailureEvent(int sequenceNumber,
                                                 const OsTime& timestamp,      ///< obtain using getCurTime(OsTime)
                                                 const UtlString& branch_id,
                                                 int via_count,
                                                 int statusCode,
                                                 const UtlString& statusMsg
                                                 )
{
   if (builderStateIsOk(CallFailureEvent))
   {
      newEvent(sequenceNumber, timestamp, CallFailureElementStart);

      mLaterElement.append(Response_Status_Start);
      char sc[11];
      sprintf(sc, "%d", statusCode);
      mLaterElement.append(sc);
      mLaterElement.append(StatusEnd_ReasonStart);
      XmlEscape(mLaterElement, statusMsg);
      mLaterElement.append(Reason_Response_End);

      mEndElement = CallFailureElementEnd;
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::callFailureEvent not allowed.");
   }
}
/**
 * Requires:
 *   - callTransferEvent
 *   - addCallData
 *   - completeCallEvent
 */
void CallStateEventBuilder_DB::callTransferEvent(int sequenceNumber,
        const OsTime& timeStamp,
        const UtlString& contact,
        const UtlString& refer_to,
        const UtlString& referred_by,
        const UtlString& request_uri)
{
    if (builderStateIsOk(CallTransferEvent))
    {
        newEvent(sequenceNumber, timeStamp, CallEventTable, CallTransferType);

        UtlString nvalue;
        replaceSingleQuotes(contact, nvalue);
        mContactElement = "\'" + nvalue + "\',";

        replaceSingleQuotes(refer_to, nvalue);
        mReferElement = "\'" + nvalue + "\',";

        replaceSingleQuotes(referred_by, nvalue);
        mReferElement += "\'" + nvalue + "\',";

        replaceSingleQuotes(request_uri, nvalue);
        mRequestUri = "\'" + nvalue + "\',";
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callEndEvent not allowed.", ModuleName);
    }
}
/**
 * Requires:
 *   - callRequestEvent
 *   - addCallData (the toTag in the addCallRequest will be a null string)
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_XML::callRequestEvent(int sequenceNumber,
                                                 const OsTime& timestamp,      ///< obtain using getCurTime(OsTime)
                                                 const UtlString& contact,
                                                 const UtlString& references,
                                                 const UtlString& branch_id,
                                                 int              via_count,
                                                 const bool callerInternal
                                                 )
{
   if (builderStateIsOk(CallRequestEvent))
   {
      newEvent(sequenceNumber, timestamp, CallRequestElementStart);

      mLaterElement.append(ContactElementStart);
      XmlEscape(mLaterElement, contact);
      mLaterElement.append(ContactElementEnd);

      mEndElement = CallRequestElementEnd;
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::callRequestEvent not allowed.");
   }
}
/**
 * Requires:
 *   - callFailureEvent
 *   - addCallData
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_DB::callFailureEvent(int sequenceNumber,
        const OsTime& timestamp,      ///< obtain using getCurTime(OsTime)
        const UtlString& branch_id,
        int via_count,
        int statusCode,
        const UtlString& statusMsg
                                               )
{
    if (builderStateIsOk(CallFailureEvent))
    {
        newEvent(sequenceNumber, timestamp, CallEventTable, CallFailureType);

        char buffer[256];
        snprintf(buffer, 256, "%d,\'%s\',", statusCode, statusMsg.data());
        mFailureElement = buffer;

        UtlString nbranchId;
        replaceSingleQuotes(branch_id, nbranchId);
        mBranchId = "\'" + nbranchId + "\',";

        snprintf(buffer, 256, "%d", via_count);
        mViaCount = buffer;

    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callFailureEvent not allowed.", ModuleName);
    }
}
/**
 * Requires:
 *   - callSetupEvent
 *   - addCallData
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_DB::callSetupEvent(int sequenceNumber,
        const OsTime& timestamp,      ///< obtain using getCurTime(OsTime)
        const UtlString& contact,
        const UtlString& calleeRoute,
        const UtlString& branch_id,
        int              via_count
                                             )
{
    if (builderStateIsOk(CallSetupEvent))
    {
        newEvent(sequenceNumber, timestamp, CallEventTable, CallSetupType);

        UtlString ncontact;
        replaceSingleQuotes(contact, ncontact);
        mContactElement = "\'" + ncontact + "\',";

        UtlString ncalleeRoute;
        replaceSingleQuotes(calleeRoute, ncalleeRoute);
        mCalleeRoute = "\'" + ncalleeRoute + "\',";

        UtlString nbranchId;
        replaceSingleQuotes(branch_id, nbranchId);
        mBranchId = "\'" + nbranchId + "\',";

        char buffer[10];
        snprintf(buffer, 10, "%d", via_count);
        mViaCount = buffer;
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callSetupEvent not allowed.", ModuleName);
    }
}
/**
 * Record a Via from the message for this event
 * Calls to this routine are in reverse cronological order - the last
 * call for an event should be the via added by the message originator
 */
void CallStateEventBuilder_DB::addEventVia(const UtlString& via
                                          )
{
    if (!builderStateIsOk(AddVia))
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callEndEvent not allowed.", ModuleName);
    }
}
/// Indicates that all information for the current call event has been added.
void CallStateEventBuilder_XML::completeCallEvent()
{
   if (builderStateIsOk(CompleteCallEvent))
   {
      mEventComplete = true;
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::completeCallEvent not allowed.");
   }
}
/// Indicates that all information for the current call event has been added.
void CallStateEventBuilder_DB::completeCallEvent()
{
    if (builderStateIsOk(CompleteCallEvent))
    {
        mEventComplete = true;
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::completeCallEvent not allowed.", ModuleName);
    }
}
/**
 * Generate a metadata event.
 * This method generates a complete event - it does not require that the callEventComplete method be called.
 */
void CallStateEventBuilder_DB::observerEvent(int sequenceNumber, ///< for ObserverReset, this should be zero
        const OsTime& timestamp,      ///< obtained using getCurTime(OsTime)
        ObserverEvent eventCode,
        const char* eventMsg ///< for human consumption
                                            )
{
    BuilderMethod eventMethod;

    switch (eventCode)
    {
    case ObserverReset:
        reset(); // because this event is ok any time, clear out any partial event.
        eventMethod = BuilderReset;
        break;
    default:
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR, "observerEvent: invalid eventCode %d", eventCode);
        eventMethod = InvalidEvent;
        break;
    }

    if (builderStateIsOk(eventMethod))
    {
        newEvent(sequenceNumber, timestamp, ObserverEventTable);

        char buffer[256];
        snprintf(buffer, 256, "%d,\'%s\'",
                 eventCode, eventMsg);
        mCurrentEvent.append(buffer);

        mCallInfo.remove(0);
        mReferElement.remove(0);
        mContactElement.remove(0);
        mReferElement.remove(0);
        mFailureElement.remove(0);
        mRequestUri.remove(0);
        mReferences.remove(0);
        mCallerInternal.remove(0);
        mCalleeRoute.remove(0);
        mBranchId.remove(0);
        mViaCount.remove(0);

        mEventComplete = true;
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR, "observerEvent: %d not allowed.", eventCode);
    }
}
/**
 * Requires:
 *   - callEndEvent
 *   - addCallData
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_XML::callEndEvent(const int sequenceNumber,
                                             const OsTime& timestamp      ///< obtain using getCurTime(OsTime)
                                             )
{
   if (builderStateIsOk(CallEndEvent))
   {
      newEvent(sequenceNumber, timestamp, CallEndElementStart);

      mEndElement = CallEndElementEnd;
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::callEndEvent not allowed.");
   }
}
/**
 * Requires:
 *   - callEndEvent
 *   - addCallData
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_DB::callEndEvent(const int sequenceNumber,
        const OsTime& timestamp      ///< obtain using getCurTime(OsTime)
                                           )
{
    if (builderStateIsOk(CallEndEvent))
    {
        newEvent(sequenceNumber, timestamp, CallEventTable, CallEndType);
        mFailureElement = CallEvent_NoFailure;
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callEndEvent not allowed.", ModuleName);
    }
}
/**
 * Requires:
 *   - callRequestEvent
 *   - addCallData (the toTag in the addCallRequest will be a null string)
 *   - addEventVia (at least for via index zero)
 *   - completeCallEvent
 */
void CallStateEventBuilder_DB::callRequestEvent(int sequenceNumber,
        const OsTime& timestamp,      ///< obtain using getCurTime(OsTime)
        const UtlString& contact,
        const UtlString& references,
        const UtlString& branch_id,
        int              via_count,
        const bool callerInternal
                                               )
{
    if (builderStateIsOk(CallRequestEvent))
    {
        newEvent(sequenceNumber, timestamp, CallEventTable, CallRequestType);

        // Translate single quotes
        UtlString nfield;
        replaceSingleQuotes(contact, nfield);
        mContactElement = "\'" + nfield + "\',";

        replaceSingleQuotes(references, nfield);
        mReferences = "\'" + nfield + "\',";

        if (callerInternal==true) {
            mCallerInternal = "\'t\',";
        }
        else {
            mCallerInternal = "\'f\',";
        }

        UtlString nbranchId;
        replaceSingleQuotes(branch_id, nbranchId);
        mBranchId = "\'" + nbranchId + "\',";

        char buffer[10];
        snprintf(buffer, 10, "%d", via_count);
        mViaCount = buffer;
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callRequestEvent not allowed.",
                                   ModuleName);
    }
}
/**
 * Record a Via from the message for this event
 * Calls to this routine are in reverse cronological order - the last
 * call for an event should be the via added by the message originator
 */
void CallStateEventBuilder_XML::addEventVia(const UtlString& via
                                            )
{
   if (builderStateIsOk(AddVia))
   {
      // construct the element locally
      UtlString viaElement;
      viaElement.append(ViaStart);
      XmlEscape(viaElement, via);
      viaElement.append(ViaEnd);

      // prepend it to the recorded vias so that the first one is first
      mViaHeader.prepend(viaElement);
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::callEndEvent not allowed.");
   }
}
/// Add the dialog and call information for the event being built.
void CallStateEventBuilder_DB::addCallData(const int cseqNumber,
        const UtlString& callId,
        const UtlString& fromTag,  /// may be a null string
        const UtlString& toTag,    /// may be a null string
        const UtlString& fromField,
        const UtlString& toField
                                          )
{
    if (builderStateIsOk(AddCallData))
    {
        // Allow for cseq field
        char buffer[32];
        snprintf(buffer, 31, "%d,", cseqNumber);
        mCallInfo = buffer;

        UtlString nvalue;
        replaceSingleQuotes(callId, nvalue);
        mCallInfo += "\'" + nvalue + "\',";

        replaceSingleQuotes(fromTag, nvalue);
        mCallInfo += "\'" + nvalue + "\',";

        replaceSingleQuotes(toTag, nvalue);
        mCallInfo += "\'" + nvalue + "\',";

        replaceSingleQuotes(fromField, nvalue);
        mCallInfo += "\'" + nvalue + "\',";

        replaceSingleQuotes(toField, nvalue);
        mCallInfo += "\'" + nvalue + "\',";
    }
    else
    {
        assert(false);
        Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                                   "%s::callEndEvent not allowed.", ModuleName);
    }
}
/// Add the dialog and call information for the event being built.
void CallStateEventBuilder_XML::addCallData(const int cseqNumber,
                                            const UtlString& callId,
                                            const UtlString& fromTag,  /// may be a null string
                                            const UtlString& toTag,    /// may be a null string
                                            const UtlString& fromField,
                                            const UtlString& toField
                                            )
{
   if (builderStateIsOk(AddCallData))
   {
      mCallInfo.append(Call_Dialog_CallId_Start);
      XmlEscape(mCallInfo, callId);
      mCallInfo.append(CallIdEnd);
      if (!fromTag.isNull())
      {
         mCallInfo.append(FromTagStart);
         XmlEscape(mCallInfo, fromTag);
         mCallInfo.append(FromTagEnd);
      }
      if (!toTag.isNull())
      {
         mCallInfo.append(ToTagStart);
         XmlEscape(mCallInfo, toTag);
         mCallInfo.append(ToTagEnd);
      }
      mCallInfo.append(DialogEnd_FromFieldStart);
      XmlEscape(mCallInfo, fromField);
      mCallInfo.append(FromFieldEnd_ToFieldStart);
      XmlEscape(mCallInfo, toField);
      mCallInfo.append(ToField_CallEnd);
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "CallStateEventBuilder_XML::callEndEvent not allowed.");
   }
}
/**
 * Generate a metadata event.
 * This method generates a complete event - it does not require that the callEventComplete method be called.
 */
void CallStateEventBuilder_XML::observerEvent(int sequenceNumber, ///< for ObserverReset, this should be zero
                                              const OsTime& timestamp,      ///< obtained using getCurTime(OsTime)
                                              ObserverEvent eventCode,
                                              const char* eventMsg ///< for human consumption
                                              )
{
   BuilderMethod eventMethod;
   switch (eventCode)
   {
   case ObserverReset:
      reset(); // because this event is ok any time, clear out any partial event.
      eventMethod = BuilderReset;
      break;
   default:
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "observerEvent: invalid eventCode %d", eventCode);
      eventMethod = InvalidEvent;
      break;
   }

   if (builderStateIsOk(eventMethod))
   {
      newEvent(sequenceNumber, timestamp, ObsMsgStart);
      char ec[11];
      sprintf(ec, "%d", eventCode);
      mCurrentEvent.append(ec);
      mCurrentEvent.append(ObsMsgMiddle);
      XmlEscape(mCurrentEvent, eventMsg);
      mCurrentEvent.append(ObsText_Schema_ObsMsg_End);
      mEventComplete = true;
   }
   else
   {
      assert(false);
      OsSysLog::add(FAC_SIP, PRI_ERR, "observerEvent: %d not allowed.", eventCode);
   }
}