#pragma once

// subtitleeditor -- a tool to create or edit subtitle
//
// https://kitone.github.io/subtitleeditor/
// https://github.com/kitone/subtitleeditor/
//
// Copyright @ 2005-2018, kitone
//
// 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; either version 3 of the License, or
// (at your option) any later version.
//
// 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, see <http://www.gnu.org/licenses/>.

#include <gtkmm.h>
#include "cfg.h"
#include "stylemodel.h"

class Document;
class SubtitleModel;

class SubtitleView : public Gtk::TreeView {
 public:
  explicit SubtitleView(Document &doc);
  ~SubtitleView();

  // return first iter select
  Gtk::TreeIter getSelected();

  // select and set the cursor on iter
  void select_and_set_cursor(const Gtk::TreeIter &iter,
                             bool start_editing = false);

  // This is a static function.
  // Return the humain label by the internal name of the column.
  static Glib::ustring get_column_label_by_name(const Glib::ustring &name);

  // Return the name of the current column focus.
  // (start, end, duration, text, translation ...)
  Glib::ustring get_current_column_name();

 protected:
  void loadCfg();

  //  create columns with the config order
  //  ["subtitle-view"] columns="number;layer;..."
  void createColumns();

  void createColumnNum();
  void createColumnLayer();
  void createColumnStart();
  void createColumnEnd();
  void createColumnDuration();
  void createColumnStyle();
  void createColumnName();
  void createColumnMarginR();
  void createColumnMarginL();
  void createColumnMarginV();
  void createColumnEffect();
  void createColumnText();
  void createColumnCPS();
  void createColumnTranslation();
  void createColumnNote();

  // Get the columns displayed from the configuration and updates.
  void update_columns_displayed_from_config();

  void on_selection_changed();

  void on_edited_layer(const Glib::ustring &path, const Glib::ustring &newtext);

  // callback utiliser pour modifier le temps directement depuis la list
  // (treeview)
  void on_edited_start(const Glib::ustring &path, const Glib::ustring &newtext);

  // callback utiliser pour modifier le temps directement depuis la list
  // (treeview)
  void on_edited_end(const Glib::ustring &path, const Glib::ustring &newtext);

  //  callback utiliser pour modifier le temps directement depuis la list
  // (treeview)
  void on_edited_duration(const Glib::ustring &path,
                          const Glib::ustring &newtext);

  // callback utiliser pour modifier le texte directement depuis la list
  // (treeview)
  void on_edited_text(const Glib::ustring &path, const Glib::ustring &newtext);

  void on_edited_translation(const Glib::ustring &path,
                             const Glib::ustring &newtext);
  void on_edited_note(const Glib::ustring &path, const Glib::ustring &newtext);

  void on_edited_effect(const Glib::ustring &path,
                        const Glib::ustring &newtext);

  // callback utiliser pour modifier le style (a partir d'un menu, cell renderer
  // combo)
  void on_edited_style(const Glib::ustring &path,
                       const Glib::ustring &newstyle);

  // callback utiliser pour modifier le nom (a partir d'un menu, cell renderer
  // combo)
  void on_edited_name(const Glib::ustring &path, const Glib::ustring &newstyle);

  void on_edited_margin_l(const Glib::ustring &path,
                          const Glib::ustring &value);
  void on_edited_margin_r(const Glib::ustring &path,
                          const Glib::ustring &value);
  void on_edited_margin_v(const Glib::ustring &path,
                          const Glib::ustring &value);

  void on_set_style_to_selection(const Glib::ustring &name);

  // COLUMN

  // Return a new column (already manage) with Gtk::Label in title.
  Gtk::TreeViewColumn *create_treeview_column(const Glib::ustring &name);

  void create_column_time(
      const Glib::ustring &name,
      const Gtk::TreeModelColumnBase &column_attribute,
      const sigc::slot<void, const Glib::ustring &, const Glib::ustring &>
          &slot_edited,
      const sigc::slot<void, const Gtk::CellRenderer *,
                       const Gtk::TreeModel::iterator &> &slot_cell_data_func,
      const Glib::ustring &tooltips = Glib::ustring());

  // Retourne le nom utiliser en interne de la column
  Glib::ustring get_name_of_column(Gtk::TreeViewColumn *column);

  // Retourne la colonne par rapport a son nom (interne)
  Gtk::TreeViewColumn *get_column_by_name(const Glib::ustring &name);

  void set_column_visible(const Glib::ustring &name, bool state);

  bool get_column_visible(const Glib::ustring &name);

  // The position of the cursor (focused cell) has changed.
  // Update the column title (bold).
  void on_cursor_changed();

  bool on_key_press_event(GdkEventKey *event);

  bool on_button_press_event(GdkEventButton *ev);

  // il y a eu des changements dans la configuration du groupe "subtitle-view"
  void on_config_subtitle_view_changed(const Glib::ustring &key,
                                       const Glib::ustring &value);

  void set_tooltips(Gtk::TreeViewColumn *column, const Glib::ustring &text);

  void cps_data_func(const Gtk::CellRenderer *renderer,
                     const Gtk::TreeModel::iterator &iter);

  void duration_data_func(const Gtk::CellRenderer *renderer,
                          const Gtk::TreeModel::iterator &iter);

  void start_time_data_func(const Gtk::CellRenderer *renderer,
                            const Gtk::TreeModel::iterator &iter);

  void end_time_data_func(const Gtk::CellRenderer *renderer,
                          const Gtk::TreeModel::iterator &iter);

  void on_config_timing_changed(const Glib::ustring &key,
                                const Glib::ustring &value);

  // Update the visible range
  // We need to update after timing change or framerate change
  void update_visible_range();

 protected:
  Document *m_refDocument;

  SubtitleColumnRecorder m_column;

  Glib::RefPtr<SubtitleModel> m_subtitleModel;
  Glib::RefPtr<StyleModel> m_styleModel;

  // pointe sur les columns par rapport a leur nom
  Gtk::TreeViewColumn *m_currentColumn{nullptr};
  std::map<Glib::ustring, Gtk::TreeViewColumn *> m_columns;

  Gtk::Menu m_menu_popup;

 protected:
  bool check_timing;
  long min_gap;
  long min_duration;
  double min_cps;
  double max_cps;
};
