
#ifndef _WB_CONTEXT_UI_H_
#define _WB_CONTEXT_UI_H_

// WB application functionality for UI


#include "wb_config.h"

#include "mdc_events.h"
#include <sigc++/sigc++.h>

#include "wb_context.h"

#include "wb_command_ui.h"

namespace bec 
{
  class ValueTreeBE;
  class ValueInspectorBE;
};

class GUIPluginBase;

namespace wb {

  class WBContext;
  class OverviewBE;
  class PhysicalOverviewBE;
  class WorkspaceOverviewBE;
  class HistoryTreeBE;
  class MiniView;
  class LayerTreeBE;
  class UserDatatypeListBE;
  class DiagramOptionsBE;

  class ModelDiagramForm;


  // this class contains functionality that the UI needs,
  // like menu/toolbar access, special form backends etc

  class MYSQLWBBACKEND_PUBLIC_FUNC WBContextUI : public sigc::trackable
  {
  public:
    WBContextUI(bool verbose);
    virtual ~WBContextUI();

    bool init(WBFrontendCallbacks *callbacks, WBOptions *options);
    
    // must be called when the frontend window is already on screen
    void init_finish(WBOptions *options);
    
    void finalize();

    bool request_quit();
    void perform_quit();
    
    void reset();

    WBContext *get_wb() { return _wb; }
    CommandUI *get_command_ui() { return &_command_ui; }

    // form/panel backends
    WorkspaceOverviewBE *get_main_overview();    
    PhysicalOverviewBE *get_physical_overview();

    bec::ValueTreeBE *get_layer_tree();
    bec::ValueInspectorBE *create_inspector_for_selection(bec::UIForm *form, std::vector<std::string> &items);
    bec::ValueInspectorBE *create_inspector_for_selection(std::vector<std::string> &items);

    std::string get_description_for_selection(bec::UIForm *form, grt::ListRef<GrtObject> &activeObjList, std::vector<std::string> &items);
    std::string get_description_for_selection(grt::ListRef<GrtObject> &activeObjList, std::vector<std::string> &items);
    void set_description_for_selection(const grt::ListRef<GrtObject> &objList, const std::string &val);

    bec::ValueTreeBE *get_catalog_tree();

    HistoryTreeBE *get_history_tree();
    FindDialogBE *get_find_dialog() { return _find_dialog; }
    
    void layer_tree_item_activate(const grt::ValueRef &value);

    DiagramOptionsBE *create_diagram_options_be(mdc::CanvasView *view);

    UserDatatypeListBE *get_usertypes_tree();

    void setup_mini_view(mdc::CanvasView *view);
    void update_mini_view_size(int w, int h);
    
    std::string get_active_diagram_info();

    // utility functions for user preferences
    void get_doc_properties(std::string& caption, std::string& version, std::string& author, std::string& project, std::string& date_created, std::string& date_changed, std::string& description);
    void set_doc_properties(const std::string &caption, const std::string &version, const std::string &author, const std::string &project, const std::string &date_created, const std::string &date_changed, const std::string &description);

    std::list<WBPaperSize> get_paper_sizes(bool descr_in_inches);
    bool add_paper_size(const std::string &name, double width, double height,
                      bool margins, double margin_top, double margin_bottom,
                      double margin_left, double margin_right);

    std::vector<std::string> get_wb_options_keys(const std::string &model);

    grt::DictRef get_model_options(const std::string &model_id);

    bool get_wb_options_value(const std::string &model, const std::string &key, std::string &value);
    void set_wb_options_value(const std::string &model, const std::string &key, const std::string &value);

    void discard_wb_model_options(const std::string &model);

    app_PageSettingsRef get_page_settings();
    void update_page_settings(const std::string &paper_type, const std::string &orientation);


    // form management
    void register_form(bec::UIForm *form);

    void set_active_form(bec::UIForm *form);
    bec::UIForm *get_active_form();

    bec::UIForm *get_active_main_form();

    ModelDiagramForm *get_diagram_form_for_diagram_id(const std::string &id) { return _model_forms[id]; }
    ModelDiagramForm *get_diagram_form(mdc::CanvasView *view);

    model_DiagramRef get_active_model_diagram(bool main_form);
    model_ModelRef get_active_model(bool main_form);

    std::string get_active_context(bool main_context= true);

    sigc::signal<void,bec::UIForm*> signal_main_form_change() { return _main_form_change_signal; }
    sigc::signal<void,bec::UIForm*> signal_form_change() { return _form_change_signal; }

    // other functionality for UI
    std::string get_title();
    std::string get_document_name();

    std::string get_view_path_for_active_view();

  private:
    friend class WBContext;
    // for use by WBContext

    void load_app_options(bool update);

    void register_diagram_form(ModelDiagramForm *view);
    void notify_diagram_created(ModelDiagramForm *view);
    void notify_diagram_destroyed(ModelDiagramForm *view);

  private:
    
    void history_changed();


    void overview_selection_changed();
    void view_selection_changed(bool, mdc::CanvasItem*, ModelDiagramForm *view);
    static void *form_destroyed(void *data);

    void activate_find_result(const GrtObjectRef &location, const GrtObjectRef &object, const std::string &text);
    void diagram_object_changed(const std::string &member, const grt::ValueRef &ovalue, ModelDiagramForm *view);

    void refresh_editor_cb(bec::BaseEditor *editor);

    void update_layer_tree();
    void update_current_diagram(bec::UIForm *form);
    
    void add_backend_builtin_commands();

    void call_undo();
    void call_redo();
  private:
    WBContext *_wb;

    // special forms/panels
    MiniView *_mini_view;

    PhysicalOverviewBE *_overview;
    WorkspaceOverviewBE *_ws_overview;
    LayerTreeBE *_layer_tree;
    HistoryTreeBE *_history_tree;
    bec::ValueTreeBE *_catalog_tree;
    FindDialogBE *_find_dialog;
    UserDatatypeListBE *_usertypes_tree;

    CommandUI _command_ui;

    // form management
    std::map<std::string, ModelDiagramForm*> _model_forms;

    bec::UIForm *_active_form;
    bec::UIForm *_active_main_form;

    sigc::signal<void,bec::UIForm*> _main_form_change_signal;
    sigc::signal<void,bec::UIForm*> _form_change_signal;
    
    
    bool _last_unsaved_changes_state;
  };
};


#endif
