#ifndef _WB_MODULE_H_
#define _WB_MODULE_H_

#include <grtpp_module_cpp.h>

#include "wb_context.h"

#include "interfaces/plugin.h"

#define WBModule_VERSION "2.0.0"

class UserDefinedTypeEditor;

namespace wb {

class WorkbenchImpl : public grt::ModuleImplBase, public PluginInterfaceImpl
{
  typedef grt::ModuleImplBase super;

public:
  WorkbenchImpl(grt::CPPModuleLoader *);

  void set_context(WBContext *wb);

  DEFINE_INIT_MODULE(WBModule_VERSION, "MySQL AB", grt::ModuleImplBase,
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::getPluginInfo),


    // Non-plugin functions
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::copyToClipboard),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::hasUnsavedChanges),

    // Model
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::newDocument),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::openModel),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::openRecentModel),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::saveModel),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::saveModelAs),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exit),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exportPNG),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exportPDF),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exportPS),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exportSVG),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::selectAll),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::selectSimilar),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::selectConnected),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::goToNextSelected),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::goToPreviousSelected),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::editSelectedFigure),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::editSelectedFigureInNewWindow),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::editObject),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::editObjectInNewWindow),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::raiseSelection),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::lowerSelection),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::newDiagram),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::toggleGrid),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::togglePageGrid),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::toggleGridAlign),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::zoomIn),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::zoomOut),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::zoomDefault),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::setFigureNotation),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::setRelationshipNotation),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::setMarker),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::goToMarker),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::startTrackingUndo),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::finishTrackingUndo),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::cancelTrackingUndo),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::addUndoListAdd),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::addUndoListRemove),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::addUndoObjectChange),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::addUndoDictSet),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::beginUndoGroup),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::endUndoGroup),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::setUndoDescription),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::createAttachedFile),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::setAttachedFileContents),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::getAttachedFileContents),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::getAttachedFileTmpPath),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::exportAttachedFileContents),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::debugShowInfo),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::debugGrtStats),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::debugValidateGRT),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::runScriptFile),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::installModuleFile),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::showUserTypeEditor),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::showDocumentProperties),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::showModelOptions),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::showOptions),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::showConnectionManager),

    DECLARE_MODULE_FUNCTION(WorkbenchImpl::input),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::confirm),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::requestFileOpen),
    DECLARE_MODULE_FUNCTION(WorkbenchImpl::requestFileSave)
    );

private:
  WBContext *_wb;
  UserDefinedTypeEditor* _current_user_type_editor;
 
  void userTypeEditorClosed();

  virtual grt::ListRef<app_Plugin> getPluginInfo();

  int copyToClipboard(const std::string &str);

  int hasUnsavedChanges();
  
  // file
  int newDocument();
  int openModel(const std::string &path);
  int openRecentModel(const std::string &index);
  int saveModel();
  int saveModelAs(const std::string &path);
  int exportPNG(const std::string &filename);
  int exportPDF(const std::string &filename);
  int exportPS(const std::string &filename);
  int exportSVG(const std::string &filename);

  int exit();


  // edit
  int selectAll();
  int selectSimilar();
  int selectConnected();

  int editSelectedFigure(const model_DiagramRef &view);
  int editSelectedFigureInNewWindow(const model_DiagramRef &view);

  int editObject(const GrtObjectRef &object);
  int editObjectInNewWindow(const GrtObjectRef &object);

  // canvas manipulation
  int raiseSelection(const model_DiagramRef &view);
  int lowerSelection(const model_DiagramRef &view);

  // view
  int newDiagram(const model_ModelRef &model);

  int toggleGrid(const model_DiagramRef &view);
  int togglePageGrid(const model_DiagramRef &view);
  int toggleGridAlign(const model_DiagramRef &view);
  int zoomIn();
  int zoomOut();
  int zoomDefault();

  int goToNextSelected();
  int goToPreviousSelected();

  int setMarker(const std::string &marker);
  int goToMarker(const std::string &marker);

  int setFigureNotation(const std::string &name, workbench_physical_ModelRef model);
  int setRelationshipNotation(const std::string &name, workbench_physical_ModelRef model);


  // undo
  int startTrackingUndo();
  int finishTrackingUndo(const std::string &description);
  int cancelTrackingUndo();
  
  int addUndoListAdd(const grt::BaseListRef &list);
  int addUndoListRemove(const grt::BaseListRef &list, int index);
  int addUndoObjectChange(const grt::ObjectRef &object, const std::string &member);
  int addUndoDictSet(const grt::DictRef &dict, const std::string &key);
  int beginUndoGroup();
  int endUndoGroup();
  int setUndoDescription(const std::string &text);

  // attached file management
  std::string createAttachedFile(const std::string &group, const std::string &tmpl);
  int setAttachedFileContents(const std::string &filename, const std::string &text);
  std::string getAttachedFileContents(const std::string &filename);
  std::string getAttachedFileTmpPath(const std::string &filename);
  int exportAttachedFileContents(const std::string &filename, const std::string &export_to);

  int runScriptFile(const std::string &filename);
  int installModuleFile(const std::string &filename);
  
  // debugging
  int debugShowInfo();
  int debugValidateGRT();
  int debugGrtStats();

  int showUserTypeEditor(const workbench_physical_ModelRef &model);
  int showDocumentProperties();
  int showModelOptions(const workbench_physical_ModelRef &model);
  int showOptions();
  int showConnectionManager();
  
  // UI
  std::string request_input_m(const std::string &caption);

  std::string input(const std::string &caption);
  int confirm(const std::string &title, const std::string &caption);
  
  std::string requestFileOpen(const std::string &caption, const std::string &extensions);
  std::string requestFileSave(const std::string &caption, const std::string &extensions);
};

};

#endif
