#include "gen_classes.h"
#include "Ports/MessagesIdentifiers.h"

#include <fstream>


/* For debugging with MMAGIC
ofstream myfile;
myfile.open ("C:\\Temp\\logs.txt", ios::out | ios::app );
myfile << "CaptureSource::PreEncodeField: " << field_id << std::endl;
myfile.close();
  */

namespace t3devlib { namespace gen {

  const char* FncRetCode::msFncRetCodeModes[] = { 
    "e_success",
    "e_error",
    "e_timeout",
    ""
  };

  const char* IOTExecMode::msExecModes[] = { 
    "e_realtime",
    "e_offline",
    ""
  };

  const char* IOTVerdictType::msVerdictTypes[] = { 
    "e_e2e",
    "e_conformance",
    ""
  };

  const char* RecordMode::msRecordModes[] = { 
    "e_norecord",
    "e_record",
    ""
  };

  const char* ProtocolFilter::msProtocolFilterModes[] = { 
    "e_sip",
    "e_dns",
    ""
  };


  void FncRetCode::Encode (Buffer& buffer) throw (EncodeError) {

    Unsigned u8(8);
    const char ** ppEnum = msFncRetCodeModes;
    const std::string & val = GetValueString();
    
    int i = 0;
    while (*(ppEnum[i]) && strcmp(ppEnum[i], val.c_str()) != 0)
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += val;
      message += '\n';
      throw EncodeError (this, message);
    }
    
    u8.SetValue(i);
    u8.Encode(buffer);
}

  void FncRetCode::Decode (Buffer& buffer) throw (DecodeError) {
    Unsigned u8(8);
    const char ** ppEnum = msFncRetCodeModes;
    
    u8.Decode(buffer);

    int i = 0;
    while (*(ppEnum[i]) && (i != u8.GetValue()) )
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += u8.GetValue();
      message += '\n';
      throw DecodeError (this, message);
    } else {
      SetValueString(ppEnum[i]);
    }
    
  }


  void IOTExecMode::Encode (Buffer& buffer) throw (EncodeError) {

    Unsigned u8(8);
    const char ** ppEnum = msExecModes;
    const std::string & val = GetValueString();
    
    int i = 0;
    while (*(ppEnum[i]) && strcmp(ppEnum[i], val.c_str()) != 0)
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += val;
      message += '\n';
      throw EncodeError (this, message);
    }
    
    u8.SetValue(i);
    u8.Encode(buffer);
}

  void IOTExecMode::Decode (Buffer& buffer) throw (DecodeError) {
   
    Unsigned u8(8);
    const char ** ppEnum = msExecModes;
    
    u8.Decode(buffer);

    int i = 0;
    while (*(ppEnum[i]) && (i != u8.GetValue()) )
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += u8.GetValue();
      message += '\n';
      throw DecodeError (this, message);
    } else {
      SetValueString(ppEnum[i]);
    }
  }

  void IOTVerdictType::Encode (Buffer& buffer) throw (EncodeError) {

    Unsigned u8(8);
    const char ** ppEnum = msVerdictTypes;
    const std::string & val = GetValueString();
    
    int i = 0;
    while (*(ppEnum[i]) && strcmp(ppEnum[i], val.c_str()) != 0)
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += val;
      message += '\n';
      throw EncodeError (this, message);
    }
    
    u8.SetValue(i);
    u8.Encode(buffer);
}

  void IOTVerdictType::Decode (Buffer& buffer) throw (DecodeError) {
   
    Unsigned u8(8);
    const char ** ppEnum = msVerdictTypes;
    
    u8.Decode(buffer);

    int i = 0;
    while (*(ppEnum[i]) && (i != u8.GetValue()) )
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += u8.GetValue();
      message += '\n';
      throw DecodeError (this, message);
    } else {
      SetValueString(ppEnum[i]);
    }

  }

  void RecordMode::Encode (Buffer& buffer) throw (EncodeError) {

    Unsigned u8(8); // 1 octet length
    // Set Value
    const char ** ppEnum = msRecordModes;
    const std::string & val = GetValueString();
    int i = 0;
    while (*(ppEnum[i]) && strcmp(ppEnum[i], val.c_str()) != 0)
      i++;
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += val;
      message += '\n';
      throw EncodeError (this, message);
    }
    u8.SetValue(i);
    u8.Encode(buffer);
}

  void RecordMode::Decode (Buffer& buffer) throw (DecodeError) {
   
    Unsigned u8(8); // 1 octet length
    const char ** ppEnum = msRecordModes;
    
    u8.Decode(buffer);

    int i = 0;
    while (*(ppEnum[i]) && (i != u8.GetValue()) )
      i++;
    
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += u8.GetValue();
      message += '\n';
      throw DecodeError (this, message);
    } else {
      SetValueString(ppEnum[i]);
    }

  }


  void ProtocolFilter::Encode (Buffer& buffer) throw (EncodeError) {

   Unsigned u8(8); // 1 octet length
    // Set Value
    const char ** ppEnum = msProtocolFilterModes;
    const std::string & val = GetValueString();
    int i = 0;
    while (*(ppEnum[i]) && strcmp(ppEnum[i], val.c_str()) != 0)
      i++;
    if (*(ppEnum[i]) == 0) {
      std::string message ("unsupported enum value '");
      message += val;
      message += '\n';
      throw EncodeError (this, message);
    }
    u8.SetValue(i);
    u8.Encode(buffer);
}

  void ProtocolFilter::Decode (Buffer& buffer) throw (DecodeError) {
  
  Unsigned u8(8); // 1 octet length
  const char ** ppEnum = msProtocolFilterModes;
  
  u8.Decode(buffer);

  int i = 0;
  while (*(ppEnum[i]) && (i != u8.GetValue()) )
    i++;
  
  if (*(ppEnum[i]) == 0) {
    std::string message ("unsupported enum value '");
    message += u8.GetValue();
    message += '\n';
    throw DecodeError (this, message);
  } else {
    SetValueString(ppEnum[i]);
  }
}

  void InterfaceInfoList::PreEncode (Buffer& buffer) throw (EncodeError)
  {
    // Set the number of parameters.
    Unsigned fieldLength(8, GetSize());
    fieldLength.Encode(buffer);
  }

  void Product::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_productName:
        {
          // Set the number of parameters.
          value = Get_productName();
          std::cout << "Product::PreEncodeField: id_productName value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      default:
        std::cerr << "Product::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "Product::PreEncodeField: fieldLength=" << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }
  

  void InterfaceInfo::PreEncode (Buffer& buffer) throw (EncodeError)
  {
    // Set union type
    Unsigned fieldLength(8, GetChosenId()); // 1 octet length
    //std::cout << "InterfaceInfo::InterfaceInfo: fieldLength=" << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
    
    if (GetChosenId() == id_IpInterfaceInfo)
    {
      // Set the number of parameters.
      IpInterfaceInfoList& list = Get_IpInterfaceInfo();
      //std::cout << "InterfaceInfo::PreEncode: id_IpInterfaceInfo size=" << list.GetSize() << std::endl;
      fieldLength.SetValue(list.GetSize());
      fieldLength.Encode(buffer);
    }
  }

  void CaptureMode::PreEncode (Buffer& buffer) throw (EncodeError)
  {
    // Set union type
    Unsigned fieldLength(8, GetChosenId()); // 1 octet length
    //std::cout << "CaptureMode::PreEncode: fieldLength=" << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }
  
  void IpInterfaceInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_domainName:
        {
          if(IsPresent(id_domainName))
          {
            // Set the string length.
            value = Get_domainName();
            std::cout << "IpInterfaceInfo::PreEncodeField: id_domainName value=" << value << " - " << value.GetLength() / 8 << std::endl;
            fieldLength.SetValue(value.GetLength() / 8);
          }
          else
          {
            fieldLength.SetValue(0);
          }
        }
        break;
      case id_IpAddress:
        {
          value = static_cast<Charstring>(Get_IpAddress());
          std::cout << "IpInterfaceInfo::PreEncodeField: id_IpAddress value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      case id_portNumbers:
        {
          PortNumberList& ports = Get_portNumbers();
          std::cout << "IpInterfaceInfo::PreEncodeField: id_portNumbers value=" << ports.GetSize() << std::endl;
          fieldLength.SetValue(ports.GetSize());
        }
        break;
      default:
        std::cerr << "IpInterfaceInfo::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "IpInterfaceInfo::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void EutInterfaceInfo::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_eut:
        {
          // Set the string length.
          value = Get_eut();
          std::cout << "EutInterfaceInfo::PreEncodeField: id_eut value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      case id_ipAddress:
        {
          value = static_cast<Charstring>(Get_ipAddress());
          std::cout << "EutInterfaceInfo::PreEncodeField: id_ipAddress value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      default:
        std::cerr << "EutInterfaceInfo::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "EutInterfaceInfo::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void LiveCapture::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_physicalInterfaces:
        {
          // Set the number of parameters.
          PhysicalInterfaceList& ifaces = Get_physicalInterfaces();
          std::cout << "LiveCapture::PreEncodeField: id_physicalInterfaces size=" << ifaces.GetSize() << std::endl;
          fieldLength.SetValue(ifaces.GetSize());
        }
        break;
      default:
        std::cerr << "LiveCapture::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "LiveCapture::PreEncodeField: fieldLength=" << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }
  

  void CaptureSource::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_sessionsPath:
        {
          // Set the string length.
          value = Get_sessionsPath();
          std::cout << "CaptureSource::PreEncodeField: id_sessionsPath value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      default:
        std::cerr << "CaptureSource::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "CaptureSource::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void MergeFileList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_mergeFileList:
        {
          // Set the number of parameters.
          FileList& list = Get_mergeFileList();
          std::cout << "MergeFileList::PreEncodeField: id_mergeFileList value=" << list.GetSize() << std::endl;
          fieldLength.SetValue(list.GetSize());
        }
        break;
      case id_mergeFilePath:
        {
          // Set the string length.
          value = Get_mergeFilePath();
          std::cout << "MergeFileList::PreEncodeField: id_mergeFilePath value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
        
      case id_mergeToolPath:
        {
          // Set the string length.
          value = Get_mergeToolPath();
          std::cout << "MergeFileList::PreEncodeField: id_mergeToolPath value=" << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
        
      default:
        std::cerr << "MergeFileList::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "MergeFileList::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void GeneralConfigurationReq::PreEncode (Buffer & buffer ) throw (EncodeError)
  {
    // Get message index
    unsigned char idx = MessagesIdentifiers::GetIdx(GetTypeName());
    if (idx == 0xff) {
      std::string message ("unsupported enum value '");
      message += GetTypeName();
      message += '\n';
      throw EncodeError (this, message);
    }
    // Set message index
    Unsigned fieldLength(8); // 1 octet length
    fieldLength.SetValue(idx);
    fieldLength.Encode(buffer);
  }

  void GeneralConfigurationReq::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8); // 2 octet length
    switch (field_id) {
      case id_captureProcessIpAddress:
        {
          value = Get_captureProcessIpAddress();
          std::cout << "GeneralConfigurationReq::id_captureProcessIpAddress: value " << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      case id_eutInfoList:
        {
          if(IsPresent(id_eutInfoList))
          {
            // Set the number of parameters.
            std::cout << "GeneralConfigurationReq::id_eutInfoList: value " << Get_eutInfoList().GetSize() << std::endl;
            fieldLength.SetValue(Get_eutInfoList().GetSize());
          }
          else
          {
            fieldLength.SetValue(0);
          }

        }
        break;
      default:
        std::cerr << "GeneralConfigurationReq::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    //std::cout << "GeneralConfigurationReq::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }
  
  void GeneralConfigurationRsp::PreDecode (Buffer& buffer) throw (DecodeError)
  {
    // Get message type.
    Unsigned messageType (8); // One byte length
    messageType.Decode (buffer);
    if (MessagesIdentifiers::GetMessage(static_cast<int>(messageType.GetValue())).length() == 0) {
      std::string message ("unsupported message type '");
      message += static_cast<int>(messageType.GetValue());
      message += '\n';
      throw DecodeError (this, message);
    }
  }
  
  void EquipmentOperationReq::PreEncode (Buffer & buffer ) throw (EncodeError)
  {
    // Get message index
    unsigned char idx = MessagesIdentifiers::GetIdx(GetTypeName());
    if (idx == 0xff) {
      std::string message ("unsupported enum value '");
      message += GetTypeName();
      message += '\n';
      throw EncodeError (this, message);
    }
    // Set message index
    Unsigned fieldLength(8); // 1 octet length
    fieldLength.SetValue(idx);
    fieldLength.Encode(buffer);
  }

  void EquipmentOperationReq::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value;
    Unsigned fieldLength(2 * 8);
    switch (field_id) {
      case id_cmd:
        {
          value = Get_cmd();
          std::cout << "EquipmentOperationReq::id_cmd: value " << value << " - " << value.GetLength() / 8 << std::endl;
          fieldLength.SetValue(value.GetLength() / 8);
        }
        break;
      case id_params:
        {
          // Set the number of parameters.
          //std::cout << "EquipmentOperationReq::id_params: " << Get_params().GetSize() << std::endl;
          fieldLength.SetValue(Get_params().GetSize());
        }
        break;
      default:
        std::cerr << "EquipmentOperationReq::PreEncodeField: Non processed field: " << field_id << std::endl;
        return;
    }
    std::cout << "EquipmentOperationReq::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }
  
  void EquipmentOperationRsp::PreDecode (Buffer& buffer) throw (DecodeError)
  {
    // Get message type.
    Unsigned messageType (8); // One byte length
    messageType.Decode (buffer);
    if (MessagesIdentifiers::GetMessage(static_cast<int>(messageType.GetValue())).length() == 0) {
      std::string message ("unsupported message type '");
      message += static_cast<int>(messageType.GetValue());
      message += '\n';
      throw DecodeError (this, message);
    }
  }
  
  void PhysicalInterfaceList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value = GetField(field_id);
    std::cout << "PhysicalInterfaceList::PreEncodeField: value " << value << " - " << value.GetLength() / 8 << std::endl;
    Unsigned fieldLength(2 * 8, value.GetLength() / 8);
    std::cout << "PhysicalInterfaceList::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void FileList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value = GetField(field_id);
    std::cout << "FileList::PreEncodeField: value " << value << " - " << value.GetLength() / 8 << std::endl;
    Unsigned fieldLength(2 * 8, value.GetLength() / 8);
    std::cout << "FileList::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void ParameterList::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
  {
    Charstring value = GetField(field_id);
    std::cout << "ParameterList::PreEncodeField: value " << value << " - " << value.GetLength() / 8 << std::endl;
    Unsigned fieldLength(2 * 8, value.GetLength() / 8);
    std::cout << "ParameterList::PreEncodeField: fieldLength " << (int)fieldLength.GetValue() << std::endl;
    fieldLength.Encode(buffer);
  }

  void StartTrafficCaptureReq::PreEncode (Buffer & buffer ) throw (EncodeError)
  {
    // Set message type
    // Get message index
    unsigned char idx = MessagesIdentifiers::GetIdx(GetTypeName());
    if (idx == 0xff) {
      std::string message ("unsupported enum value '");
      message += GetTypeName();
      message += '\n';
      throw EncodeError (this, message);
    }
    // Set message index
    Unsigned fieldLength(8); // 1 octet length
    fieldLength.SetValue(idx);
    fieldLength.Encode(buffer);
  }

  void StartTrafficCaptureRsp::PreDecode (Buffer& buffer) throw (DecodeError)
  {
    // Get message type.
    Unsigned messageType (8); // One byte length
    messageType.Decode (buffer);
    if (MessagesIdentifiers::GetMessage(static_cast<int>(messageType.GetValue())).length() == 0) {
      std::string message ("unsupported message type '");
      message += static_cast<int>(messageType.GetValue());
      message += '\n';
      throw DecodeError (this, message);
    }
  }
  
  void StopTrafficCaptureReq::PreEncode (Buffer & buffer ) throw (EncodeError)
  {
    // Get message index
    unsigned char idx = MessagesIdentifiers::GetIdx(GetTypeName());
    if (idx == 0xff) {
      std::string message ("unsupported enum value '");
      message += GetTypeName();
      message += '\n';
      throw EncodeError (this, message);
    }
    // Set message index
    Unsigned fieldLength(8); // 1 octet length
    fieldLength.SetValue(idx);
    fieldLength.Encode(buffer);
  }

  void StopTrafficCaptureRsp::PreDecode (Buffer& buffer) throw (DecodeError)
  {
    // Get message type.
    Unsigned messageType (8); // One byte length
    messageType.Decode (buffer);
    if (MessagesIdentifiers::GetMessage(static_cast<int>(messageType.GetValue())).length() == 0) {
      std::string message ("unsupported message type '");
      message += static_cast<int>(messageType.GetValue());
      message += '\n';
      throw DecodeError (this, message);
    }
  }
  
  void SetFilterReq::PreEncode (Buffer & buffer ) throw (EncodeError)
  {
    // Get message index
    unsigned char idx = MessagesIdentifiers::GetIdx(GetTypeName());
    if (idx == 0xff) {
      std::string message ("unsupported enum value '");
      message += GetTypeName();
      message += '\n';
      throw EncodeError (this, message);
    }
    // Set message index
    Unsigned fieldLength(8); // 1 octet length
    fieldLength.SetValue(idx);
    fieldLength.Encode(buffer);
  }
  
  void SetFilterRsp::PreDecode (Buffer& buffer) throw (DecodeError)
  {
    // Get message type.
    Unsigned messageType (8); // One byte length
    messageType.Decode (buffer);
    if (MessagesIdentifiers::GetMessage(static_cast<int>(messageType.GetValue())).length() == 0) {
      std::string message ("unsupported message type '");
      message += static_cast<int>(messageType.GetValue());
      message += '\n';
      throw DecodeError (this, message);
    }
  }
  
  void Status::PreDecodeField(int field_id, Buffer& buffer) throw (DecodeError)
  {
    switch (field_id)
    {
      case id_code:
        break;
      case id_reason: // Set length
        {
          Unsigned reason (2 * 8);
          reason.Decode (buffer);
          if (reason.GetValue() == 0)
          {
            std::cout << "Status::PreDecodeField: Set reason omitted" << std::endl;
            SetHypFieldIsPresent(id_reason, 0);
          }
          else
          {
            std::cout << "Status::PreDecodeField: Set length to " << reason.GetValue() << std::endl;
            SetHypFieldIsPresent(id_reason, 1);
            SetHypFieldLength (id_reason, reason.GetValue() * 8);
          }
        }
        break;
      default:
        std::cerr << "Status::PreDecodeField: Non processed field: " << field_id << std::endl;
        return;
    }
  }

  
}} // namespaces
