/* 
 * Copyright (c) 2010, 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 __GRT_SHELL_WINDOW_H__
#define __GRT_SHELL_WINDOW_H__

#include "grt/grt_manager.h"
//#include "wb_context.h"

namespace wb {
  class WBContext;
};

#include "mforms/treenodeview.h"
#include "mforms/code_editor.h"
#include "mforms/menu.h"
#include "mforms/splitter.h"
#include "mforms/tabview.h"
#include "mforms/panel.h"
#include "mforms/textentry.h"
#include "mforms/textbox.h"
#include "mforms/form.h"
#include "mforms/label.h"
#include "mforms/button.h"
#include "mforms/selector.h"
#include "mforms/box.h"

class GRTCodeEditor;
class PythonDebugger;

class GRTShellWindow : public mforms::Form
{
  friend class PythonDebugger;
  
public:
  GRTShellWindow(wb::WBContext* context);
  
  bec::GRTManager *grtm();
  
  virtual void show(bool flag=true);
  
  bool execute_script(const std::string &script, const std::string &language);
  
  GRTCodeEditor *add_editor(bool is_script, const std::string &language);
  void add_new_script();
  void open_script_file();
  
  GRTCodeEditor *show_file_at_line(const std::string &path, int line);
  
  void open_file_in_editor(const std::string &path, bool is_script);
  
  void close_editor(GRTCodeEditor *editor);
  void refresh_files();

  void set_editor_title(GRTCodeEditor *editor, const std::string &title);

  bool request_quit();
  
  bool add_output(const std::string &text);  
  void activate_output_tab();

  GRTCodeEditor* get_editor_for(const std::string& path, bool select_tab);
  GRTCodeEditor *get_active_editor();

  void on_file_save(const std::string &file);
  
protected:
  wb::WBContext* _context;
  
  mforms::Box _toolbar;
  mforms::Button *_save_button;
  mforms::Button *_save_as_button;
  mforms::Button *_clear_script_output_button;
  mforms::Button *_close_script_tab_button;

  mforms::Button *_run_button;
  mforms::Button *_step_button;
  mforms::Button *_step_into_button;
  mforms::Button *_step_out_button;
  mforms::Button *_continue_button;
  mforms::Button *_stop_button;
  mforms::Button *_pause_button;
  
  mforms::Box _content;
  mforms::Box _padding_box;
  mforms::Splitter _hsplitter;
#ifdef _WIN32
  mforms::Panel _side_header_panel;
#endif
  mforms::TabView _side_tab;
  mforms::TabView _main_tab;
  
  mforms::Button _file_add;
  mforms::Button _file_delete;
  mforms::TreeNodeView* _files_tree;
  mforms::Menu _files_menu;

  mforms::Box _global_box1;
  mforms::Box _global_box2;
  mforms::Splitter _global_splitter;
  mforms::Selector _global_combo;
  mforms::TreeNodeView _global_tree;
  mforms::TextEntry _global_entry;
  mforms::TreeNodeView _global_list;
  mforms::Menu _global_menu;
  bec::ValueInspectorBE *_inspector;

  mforms::Box _classes_box;
  mforms::Splitter _classes_splitter;
  mforms::Selector _classes_sorting;
  mforms::TreeNodeView _classes_tree;
  mforms::TextBox _classes_text;

  mforms::Splitter _modules_splitter;
  mforms::TreeNodeView _modules_tree;
  mforms::TextBox _modules_text;
  
  mforms::Splitter _notifs_splitter;
  mforms::TreeNodeView _notifs_tree;
  mforms::TextBox _notifs_text;
  
  mforms::Splitter _right_splitter;
  
  mforms::Box _shell_box;
  mforms::TextBox _shell_text;
  mforms::Box _shell_hbox;
  mforms::Label _shell_prompt;
  mforms::TextEntry _shell_entry;
  
  mforms::TabView _lower_tab;
#ifdef _WIN32
  mforms::Panel _lower_header_panel;
#endif
  mforms::TextBox _output_text;
  int _lower_tab_height;
  
  mforms::Splitter _snippet_splitter;
  mforms::Box _snippet_page;
  mforms::TreeNodeView* _snippet_list;
  mforms::Button* _snippet_delete_button;
  mforms::Button* _snippet_copy_button;
  mforms::CodeEditor _snippet_text;

  mforms::Menu _snippet_menu;
  int _global_snippet_count;
  std::string _comment_prefix;
  std::string _script_extension;

  PythonDebugger *_debugger;  

  std::vector<GRTCodeEditor*> _editors;
  
  void refresh_all();
  void side_tab_changed();

  bool capture_output(const grt::Message &msg, void *sender, bool send_to_output);
  
  void shell_action(mforms::TextEntryAction action);

  void handle_prompt(const std::string &text);
  void handle_output(const std::string &text);
  void handle_error(const std::string &text, const std::string &detail);
  
  void handle_global_menu(const std::string &action);
  
  void global_selected();
  void class_selected();
  void module_selected();
  void notif_selected();
  
  void delete_selected_file();

  void file_list_activated(mforms::TreeNodeRef node, int column);
  void add_files_from_dir(mforms::TreeNodeRef parent, const std::string &dir, bool is_script);
  
  void load_snippets_from(const std::string &path);
  void save_snippets();
  void refresh_snippets();
  void add_snippet();
  void del_snippet();
  void copy_snippet();
  void run_snippet();
  void scriptize_snippet();
  void snippet_selected();
  void snippet_changed(int line, int linesAdded);
  
  void snippet_menu_activate(const std::string &action);
  void file_menu_activate(const std::string &action);

  void shell_closed();

  void load_state();
  void save_state();

  void on_tab_changed();
  bool on_tab_closing(int index);
  void on_tab_closed(int index);
  
private:
  mforms::Button *add_tool_button(const std::string &image,
                       const boost::function<void ()> &action,
                       const std::string &tooltip,
                       bool left=true);
  void add_tool_separator();

  void execute_file();
  void save_file(bool save_as);
  void close_tab();
  
  void refresh_modules_tree();
  std::string get_module_node_description(const mforms::TreeNodeRef &node);
  
  void refresh_classes_tree();
  void refresh_classes_tree_by_name();
  void refresh_classes_tree_by_hierarchy();
  void refresh_classes_tree_by_package();
  std::string get_class_node_description(const mforms::TreeNodeRef &node);

  void globals_expand_toggle(const mforms::TreeNodeRef &node, bool expanded);
  std::string get_global_path_at_node(const mforms::TreeNodeRef &node);
  grt::ValueRef get_global_at_node(const mforms::TreeNodeRef &node);
  void refresh_globals_tree();
  
  void refresh_global_list();
  
  void refresh_notifs_list();
private:
  void debug_step();
  void debug_step_into();
  void debug_step_out();
  void debug_continue();
  void debug_stop();
  void debug_pause();
};

#endif
