#ifndef __TABLE_EDITOR_H__
#define __TABLE_EDITOR_H__

#include "DBObjectEditorBE.h"
#include "GrtTemplates.h"
#include "grtdb/editor_table.h"

namespace MySQL {
namespace Grt {
namespace Db {

ref class TableEditorBE;
ref class IndexListBE;
ref class FKConstraintListBE;

public ref class TableColumnsListBE : public MySQL::Grt::ListModel
{
public:
  enum class ColumnListColumns {
    Name = ::bec::TableColumnsListBE::Name,
      Type = ::bec::TableColumnsListBE::Type,
      IsPK = ::bec::TableColumnsListBE::IsPK,
      IsNotNull = ::bec::TableColumnsListBE::IsNotNull,
      IsBinary = ::bec::TableColumnsListBE::IsBinary,
      IsUnsigned = ::bec::TableColumnsListBE::IsUnsigned,
      IsZerofill = ::bec::TableColumnsListBE::IsZerofill,
      Flags = ::bec::TableColumnsListBE::Flags,
      Default = ::bec::TableColumnsListBE::Default,
      Charset = ::bec::TableColumnsListBE::Charset,
      Collation = ::bec::TableColumnsListBE::Collation,
      HasCharset = ::bec::TableColumnsListBE::HasCharset,
      Comment = ::bec::TableColumnsListBE::Comment,
      LastColumn = ::bec::TableColumnsListBE::LastColumn
  };
  
  //TableColumnsListBE(TableEditorBE^ owner);

  TableColumnsListBE(::bec::TableColumnsListBE *inn);

  List<String^>^ get_datatype_names()
  {
    return CppStringListToNative(get_unmanaged_object()->get_datatype_names());
  }


  inline ::bec::TableColumnsListBE *get_unmanaged_object()
  { return static_cast<::bec::TableColumnsListBE *>(inner); }

  bool get_row(NodeId^ node,
               [Out] String^ %name,
               [Out] String^ %type,
               [Out] bool^ %ispk,
               [Out] bool^ %notnull,
               [Out] bool^ %isbinary,
               [Out] bool^ %isunsigned,
               [Out] bool^ %iszerofill,
               [Out] String^ %flags,
               [Out] String^ %defvalue,
               [Out] String^ %charset,
               [Out] String^ %collation,
               [Out] String^ %comment);
};

public ref class IndexColumnsListBE : public ListModel
{
public:
  enum class IndexColumnsListColumns {
      Name = ::bec::IndexColumnsListBE::Name,
      Descending = ::bec::IndexColumnsListBE::Descending,
      Length = ::bec::IndexColumnsListBE::Length,
      OrderIndex = ::bec::IndexColumnsListBE::OrderIndex
  };
  
  IndexColumnsListBE(IndexListBE^ owner);

  IndexColumnsListBE(::bec::IndexColumnsListBE *inn);

  inline ::bec::IndexColumnsListBE *get_unmanaged_object()
  { return static_cast<::bec::IndexColumnsListBE *>(inner); }

  void set_column_enabled(NodeId^ node, bool flag);
  bool get_column_enabled(NodeId^ node);

  int get_max_order_index();
};

public ref class IndexListBE : public ListModel
{ 
public:
  enum class IndexListColumns {
      Name = ::bec::IndexListBE::Name,
      Type = ::bec::IndexListBE::Type,
      Comment = ::bec::IndexListBE::Comment
  };
  
  IndexListBE(TableEditorBE^ owner);

  IndexListBE(::bec::IndexListBE *inn);

  inline ::bec::IndexListBE *get_unmanaged_object()
  { return static_cast<::bec::IndexListBE *>(inner); }
    
  IndexColumnsListBE^ get_columns();
  
  //db_Index get_selected_index();
  void select_index(NodeId^ node);

  // cannot create a wrapper instance here
  //TableEditorBE *get_owner() { return _owner; }
};

public ref class FKConstraintColumnsListBE : public ListModel
{
public:
  enum class FKConstraintColumnsListColumns {
    Enabled = ::bec::FKConstraintColumnsListBE::Enabled,
    Column = ::bec::FKConstraintColumnsListBE::Column,
    RefColumn = ::bec::FKConstraintColumnsListBE::RefColumn
  };
  
  FKConstraintColumnsListBE(FKConstraintListBE^ owner);

  FKConstraintColumnsListBE(::bec::FKConstraintColumnsListBE *inn);

  inline ::bec::FKConstraintColumnsListBE *get_unmanaged_object()
  { return static_cast<::bec::FKConstraintColumnsListBE *>(inner); }

  List<String^>^ get_ref_columns_list(NodeId ^node);

  void set_column_is_fk(NodeId^ node, bool flag);
  bool get_column_is_fk(NodeId^ node);
};

public ref class FKConstraintListBE : public ListModel
{
public:
  enum class FKConstraintListColumns {
      Name = ::bec::FKConstraintListBE::Name,
      OnDelete = ::bec::FKConstraintListBE::OnDelete,
      OnUpdate = ::bec::FKConstraintListBE::OnUpdate,
      RefTable = ::bec::FKConstraintListBE::RefTable,
      Comment = ::bec::FKConstraintListBE::Comment
  };

  FKConstraintListBE(TableEditorBE^ owner);

  FKConstraintListBE(::bec::FKConstraintListBE *inn);

  inline ::bec::FKConstraintListBE *get_unmanaged_object()
  { return static_cast<::bec::FKConstraintListBE *>(inner); }
  
  //NodeId^ add_column(String^ column_name);

  //NodeId^ add_column(const db_Column &column, const db_ForeignKey &fk= db_ForeignKey());
  
  void select_fk(NodeId^ node);

  //db_ForeignKey get_selected_fk();
  
  //TableEditorBE *get_owner() { return _owner; }

  FKConstraintColumnsListBE^ get_columns();
};

public ref class TableEditorBE : public DBObjectEditorBE
{
protected:
  TableEditorBE(::bec::TableEditorBE *inn)
    : DBObjectEditorBE(inn)
  {}

public:
  //virtual db_DatabaseObject get_dbobject() { return get_table(); }
  //virtual db_Table get_table()= 0;

  ::bec::TableEditorBE *get_unmanaged_object()
  { return static_cast<::bec::TableEditorBE *>(inner); }

  IndexListBE^ get_indexes();

  FKConstraintListBE^ get_fks();

  MySQL::Grt::GridModel^ get_inserts_grid() { return gcnew GridModel(get_unmanaged_object()->get_inserts_grid()); }

  bool update_inserts_grid() { return get_unmanaged_object()->update_inserts_grid(); }
  void update_from_inserts_grid() { get_unmanaged_object()->update_from_inserts_grid(); }

  bool set_inserts(String^ inserts)
  { return get_unmanaged_object()->set_inserts(NativeToCppString(inserts)); }

  String^ get_inserts()
  { return CppStringToNative(get_unmanaged_object()->get_inserts()); }


  // table options
  //...

  // column editing
  NodeId^ add_column(String^ name);

  void remove_column(NodeId^ column);

  //db_Column get_column_with_name(const std::string &name);

  // fk editing
  NodeId^ add_fk(String^ name);

  void remove_fk(NodeId^ fk);

  NodeId^ add_fk_with_columns(List<NodeId ^> ^columns);

  // index editing
  NodeId^ add_index(String^ name);

  void remove_index(NodeId^ index);

  NodeId^ add_index_with_columns(List<NodeId ^> ^columns);

  // helper utils for columns
  //bool parse_column_type(const std::string &str, db_Column &column);
  //std::string format_column_type(db_Column &column);

  List<String^>^ get_index_types();
};

} // namespace Db
} // namespace Grt
} // namespace MySQL

#endif // __TABLE_EDITOR_H__