// subtitleeditor -- a tool to create or edit subtitle
//
// https://subtitleeditor.github.io/subtitleeditor/
// https://github.com/subtitleeditor/subtitleeditor/
//
// subtitleeditor is Copyright @ 2005-2018, kitone
// this file is Copyright 2024 Eltomito <tomaspartl@centrum.cz>
// this file is Copyright 2025 felagund <tomashnyk@gmail.com>
//
// This subtitleeditor plugin finds the subtitle
// at the current player position
//
// 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 <debug.h>
#include <extension/action.h>
// #include <i18n.h>
#include <player.h>
#include <utility.h>

#include <algorithm>
#include <cmath>

class FindByTimePlugin : public Action {
  public:
   FindByTimePlugin() {
      activate();
      update_ui();
   }

   ~FindByTimePlugin() {
      deactivate();
   }

   /*
    */
   void activate() {
      se_dbg(SE_DBG_PLUGINS);

      // actions
      action_group = Gtk::ActionGroup::create("FindByTimePlugin");

      action_group->add(
         Gtk::Action::create("find-by-time", _("Find Subtitle By Time"), _("Find the subtitle nearest to the current player position")),
         sigc::mem_fun(*this, &FindByTimePlugin::on_find_by_time));

      // ui
      Glib::RefPtr<Gtk::UIManager> ui = get_ui_manager();

      ui_id = ui->new_merge_id();

      ui->insert_action_group(action_group);

      ui->add_ui(ui_id, "/menubar/menu-tools/find-by-time", "find-by-time", "find-by-time");
   }

   /*
    */
   void deactivate() {
      se_dbg(SE_DBG_PLUGINS);

      Glib::RefPtr<Gtk::UIManager> ui = get_ui_manager();

      ui->remove_ui(ui_id);
      ui->remove_action_group(action_group);
   }

   /*
    */
   void update_ui() {
      se_dbg(SE_DBG_PLUGINS);

      bool visible = (get_current_document() != NULL);

      action_group->get_action("find-by-time")->set_sensitive(visible);
   }

  protected:
   /*
    */
   void on_find_by_time() {
      se_dbg(SE_DBG_PLUGINS);

      Document* doc = get_current_document();
      g_return_if_fail(doc);

      Subtitles subs = doc->subtitles();

      long playerpos = get_subtitleeditor_window()->get_player()->get_position();
      long min_distance = 36000000;
      bool no_inside = true;
      Subtitle closest_sub;
      long distance;

      Subtitle cursub = subs.get_first();
      if (!cursub) {
         doc->flash_message(_("No subtitles, cannot find the nearest."));
         return;
      }

      for (Subtitle cursub = subs.get_first(); cursub; cursub = subs.get_next(cursub)) {
         if ((cursub.get_start().totalmsecs <= playerpos) && (cursub.get_end().totalmsecs >= playerpos)) {
            no_inside = false;
            doc->subtitles().select(cursub);
            doc->emit_signal("subtitle-selection-changed");
            break;
         } else {
            distance = std::min(std::abs(playerpos - cursub.get_start().totalmsecs), std::abs(playerpos - cursub.get_end().totalmsecs));
            if (distance < min_distance) {
               min_distance = distance;
               closest_sub = cursub;
            }
         }
      }
      if (no_inside) {
         doc->subtitles().select(closest_sub);
         doc->emit_signal("subtitle-selection-changed");
      }
   }

  protected:
   Gtk::UIManager::ui_merge_id ui_id;
   Glib::RefPtr<Gtk::ActionGroup> action_group;
};

REGISTER_EXTENSION(FindByTimePlugin)
