/*
 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef _WB_CONTEXT_UI_H_
#define _WB_CONTEXT_UI_H_

// WB application functionality for UI

#include "wb_config.h"

#include "mdc_events.h"

#include "wb_context.h"

#include "wb_command_ui.h"
#include "home_screen.h"
#include "starter_popup.h"
#include "base/trackable.h"
#include "base/notifications.h"

#include "model/wb_user_datatypes.h"

namespace bec 
{
  class ValueTreeBE;
  class ValueInspectorBE;
};

class GUIPluginBase;
class GRTShellWindow;
class OutputView;
class PluginInstallWindow;
class AddOnDownloadWindow;

namespace wb {
  
  class WBContext;
  class OverviewBE;
  class PhysicalOverviewBE;
  class HistoryTreeBE;
  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 base::trackable, base::Observer
  {
  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();
    bool is_quitting() { return _quitting; };
    
    void reset();

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

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

    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; }
    
    DiagramOptionsBE *create_diagram_options_be(mdc::CanvasView *view);

    UserDatatypeListBE *get_usertypes_tree();
    
    GRTShellWindow *get_shell_window();

    std::string get_active_diagram_info();
    
    void activate_figure(const grt::ValueRef &value);
    
    // 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,
                              const grt::Type default_type= grt::AnyType);

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

    app_PageSettingsRef get_page_settings();


    // 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();

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

    boost::signals2::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_diagram_path(const model_DiagramRef &diagram);

    void show_output();
    
    void refresh_home_instances(int selected_index=0);
    void refresh_home_connections(int selected_index=0);
    void refresh_home_models(int selected_index=0);
    void refresh_home_starters();
    bool home_screen_closing();

    bool start_plugin_install(const std::string &path);
    void start_plugin_net_install(const std::string &url);
    
  private:
    friend class WBContext;
    // for use by WBContext

    void load_app_options(bool update);

    void history_changed();

    void overview_selection_changed();
    friend class WBContextModel; // for these callbacks, remove once everythign is moved there

    static void *form_destroyed(void *data);

    void activate_find_result(const GrtObjectRef &location, const GrtObjectRef &object, const std::string &text);

    void refresh_editor_cb(bec::BaseEditor *editor);

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

    void show_home_screen();
    void show_web_page(const std::string& url, bool internal_browser);
    void show_help_index();
    void locate_log_file();
    void show_log_file();

    void handle_home_action(HomeScreenAction action, const grt::ValueRef &object);
    void handle_starter_action(StarterAction action, const app_StarterRef &starter);
    void handle_home_context_menu(HomeScreenListType list, const grt::ValueRef &object, const std::string &action);

    void start_plugin(const std::string& title, const std::string& command, bool force_external= false);

    virtual void handle_notification(const std::string &name, void *sender, base::NotificationInfo &info);
    
    static void home_action_callback(HomeScreenAction action, const grt::ValueRef &object, WBContextUI *self);
    static void starter_action_callback(StarterAction action, const app_StarterRef &object, void *self);
    
  private:
    WBContext *_wb;

    // special forms/panels
    GRTShellWindow *_shell_window;
    HomeScreen* _home_screen;
    HistoryTreeBE *_history_tree;
    bec::ValueTreeBE *_catalog_tree;
    FindDialogBE *_find_dialog;
    UserDatatypeListBE _usertypes_tree;
    OutputView *_output_view;
    AddOnDownloadWindow *_addon_download_window;
    PluginInstallWindow *_plugin_install_window;

    CommandUI _command_ui;
        
    // form management
    bec::UIForm *_active_form;
    bec::UIForm *_active_main_form;

    boost::signals2::signal<void (bec::UIForm*)> _form_change_signal;
    
    
    bool _last_unsaved_changes_state;
    bool _initializing;
    bool _quitting;
  };
};


#endif
