#ifndef __GRT_TEMPLATES_H__
#define __GRT_TEMPLATES_H__

#include "ConvUtils.h"

// This file should not contain any compilable .net public code
// because it is included by many projects, and any .net public code
// will cause conflicts
using namespace System;
using namespace System::Collections::Generic;

namespace MySQL {
namespace Grt {

template<typename S, typename T>
static List<T^>^ CppVectorToObjectList(const std::vector<S>& input)
{
  typedef const std::vector<S> SourceContainerType;
  typedef List<T^> 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(gcnew T(*i));

  return result;
}

// this conversion function is for simple types that map managed objects to
// a native c++ object used by value, such as e.g. ::bec::NodeId

template<typename S, typename T>
static std::vector<T> ObjectListToCppVector(List<S^>^ input)
{
  typedef const List<S^>^ SourceContainerType;
  typedef std::vector<T> TargetContainerType;

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

  return result;
}

template<typename S, typename T>
static List<T^>^ CppListToObjectList(const std::list<S>& input)
{
  typedef const std::list<S> SourceContainerType;
  typedef List<T^> 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(gcnew T(*i));

  return result;
}

// this conversion function is for simple types that map managed objects to
// a native c++ object used by value, such as e.g. ::bec::NodeId

template<typename S, typename T>
static std::list<T> ObjectListToCppList(List<S^>^ input)
{
  typedef const List<S^>^ SourceContainerType;
  typedef std::list<T> TargetContainerType;

  TargetContainerType result(static_cast<int>(input->Count));
  
  for each(S^ listitem in input)
    result.push_back(*listitem->get_unmanaged_object());

  return result;
}


template<typename S, typename T>
static List<T>^ CppListToNativeList(const std::list<S>& input)
{
  typedef const std::list<S> SourceContainerType;
  typedef List<T> 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(T(*i));

  return result;
}

// this conversion function is for simple types that map managed objects to
// a native c++ object used by value, such as e.g. ::bec::NodeId

template<typename S, typename T>
static std::list<T> NativeListToCppList(List<S>^ input)
{
  typedef const List<S>^ SourceContainerType;
  typedef std::list<T> TargetContainerType;

  TargetContainerType result(static_cast<int>(input->Count));

  for each(S listitem in input)
    result.push_back(listitem);

  return result;
}


template <class T>
struct EditorCentry
{
  T *editor;
  EditorCentry(T *editor)
    : editor(editor)
  {
    editor->DisableAutoRefresh();
  }
  ~EditorCentry()
  {
    editor->EnableAutoRefresh();
  }
  T& operator *() { return *editor; }
  T& operator ->() { return *editor; }
  operator T* () {return editor;}
  operator T& () {return *editor;}
};

} // namespace Grt



} // namespace MySQL

#endif // __GRT_TEMPLATES_H__
