#ifndef __CONV_UTILS_H__
#define __CONV_UTILS_H__

#include <vcclr.h>
#include <string>
#include <vector>
#include <list>

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;

namespace MySQL {
  
static String^ CppStringToNative(const std::string &str)
{
  String^ result = gcnew String(str.c_str(), 0, (int) str.size(), Encoding::UTF8);
  
  return result->Replace("\n", "\r\n");
}

static std::string NativeToCppString(String^ str)
{
  if (str == nullptr)
    return "";

  array<unsigned char>^ chars= Encoding::UTF8->GetBytes(str->Replace("\r\n", "\n"));
  if (chars == nullptr || chars->Length == 0)
    return "";

  pin_ptr<unsigned char> char_ptr= &chars[0];
  std::string result((char*) char_ptr);
  return result;
}

static List<String^>^ CppStringListToNative(const std::vector<std::string> &input)
{
  int cap = static_cast<int>(input.size());
  List<String^>^ result= gcnew List<String^>(cap);
  std::vector<std::string>::const_iterator e= input.end();
  
  for (std::vector<std::string>::const_iterator i= input.begin(); i != e; i++)
    result->Add(CppStringToNative(*i));
  return result;
}

static std::vector<std::string> NativeToCppStringList(List<String^>^ input)
{
  std::vector<std::string> result;
  result.reserve(input->Count);
  for each(String ^str_item in input)
    result.push_back(NativeToCppString(str_item));
  return result;
}

static std::list<std::string> NativeToCppStringList2(List<String^>^ input)
{
  std::list<std::string> result;
  for each(String ^str_item in input)
    result.push_back(NativeToCppString(str_item));
  return result;
}

static List<String^>^ CppStringListToNative2(const std::list<std::string> &input)
{
  int cap = static_cast<int>(input.size());
  List<String^>^ result= gcnew List<String^>(cap);
  std::list<std::string>::const_iterator e= input.end();
  
  for (std::list<std::string>::const_iterator i= input.begin(); i != e; i++)
    result->Add(CppStringToNative(*i));
  return result;
}

static List<int>^ CppVectorToIntList(const std::vector<int>& input)
{
  typedef const std::vector<int> SourceContainerType;
  typedef List<int> TargetContainerType;

  TargetContainerType^ result= gcnew TargetContainerType(static_cast<int>(input.size()));
  SourceContainerType::const_iterator e= input.end();
  
  for(SourceContainerType::const_iterator i= input.begin(); i != e; i++)
    result->Add(*i);

  return result;
}

static std::vector<int> IntListToCppVector(List<int>^ input)
{
  typedef const List<int>^ SourceContainerType;
  typedef std::vector<int> TargetContainerType;

  TargetContainerType result;
  result.reserve(static_cast<int>(input->Count));
  
  for each(int listitem in input)
    result.push_back(listitem);

  return result;
}

} // namespace MySQL

#endif // __CONV_UTILS_H__
