# -*- coding: utf-8 -*-

# 通知管理プラグイン

require 'mui/gtk_tree_view_pretty_scroll'

require_relative 'model_selector'
require_relative 'activity_view'

require 'set'

# アクティビティタブに保持する通知の数
UserConfig[:activity_max] ||= 1000

Plugin.create(:activity_gtk) do
  @contains_uris = Set.new

  # そのイベントをミュートするかどうかを返す(trueなら表示しない)
  def mute?(params)
    mute_kind = UserConfig[:activity_mute_kind]
    if mute_kind.is_a?(Array) && (mute_kind.map(&:to_s).include? params[:kind].to_s)
      return true
    end
    mute_kind_related = UserConfig[:activity_mute_kind_related]
    mute_kind_related && (mute_kind_related.map(&:to_s).include?(params[:kind].to_s) && !params[:related])
  end

  # アクティビティの古い通知を一定時間後に消す
  def reset_activity(model)
    return if model.destroyed?
    Delayer.new(delay: 60) do
      unless model.destroyed?
        iters = model.to_enum(:each).to_a
        remove_count = iters.size - UserConfig[:activity_max]
        if remove_count > 0
          iters[-remove_count, remove_count].each do |_m, _p, iter|
            @contains_uris.delete(iter[Plugin::ActivityGtk::ActivityView::URI])
            model.remove(iter)
          end
        end
        reset_activity(model)
      end
    end
  end

  def gen_icon_modifier(tree_model, activity)
    ->(loaded_icon) {
      uri_string = activity.uri.to_s.freeze
      if !tree_model.destroyed? && @contains_uris.include?(uri_string)
        selected_iter = tree_model.to_enum(:each).lazy.map { |_m, _p, iter|
          iter
        }.find do |iter|
          iter[Plugin::ActivityGtk::ActivityView::URI] == uri_string
        end
        selected_iter[Plugin::ActivityGtk::ActivityView::ICON] = loaded_icon if selected_iter
      end
    }
  end

  activity_view = Plugin::ActivityGtk::ActivityView.new(self)
  activity_view_sw = Gtk::ScrolledWindow.new.add activity_view
  activity_description = Gtk::IntelligentTextview.new
  activity_status = Gtk::Label.new
  activity_model_selector = Plugin::ActivityGtk::ModelSelector.new

  reset_activity(activity_view.model)

  # TODO: gtk3
  # activity_scroll_view.
  #   set_height_request(88)
  # activity_detail_view.
  #   set_height_request(128)

  tab(:activity, _('アクティビティ')) do
    set_icon Skin[:activity]
    activity_status.halign = :end
    detail_view = Gtk::Grid.new
                    .tap { |w| w.orientation = :vertical }
                    .add(Gtk::ScrolledWindow.new
        .tap { |w|
          w.expand = true
          w.hscrollbar_policy = :never
          w.vscrollbar_policy = :automatic
        }
        .add(activity_description))
                    .add(Gtk::ScrolledWindow.new.tap do |w|
                           w.set_policy(:automatic, :never)
                           w.add(activity_model_selector)
                         end)
                    .add(activity_status)

    nativewidget(
      Gtk::Paned.new(:vertical)
        .pack1(activity_view_sw, resize: true, shrink: true)
        .pack2(detail_view, resize: true, shrink: false)
    )
  end

  activity_view.ssc('cursor-changed') do |this|
    iter = this.selection.selected
    if iter
      activity_description.rewind(iter[Plugin::ActivityGtk::ActivityView::MODEL].description)
      activity_status.set_text(iter[Plugin::ActivityGtk::ActivityView::DATE])
      activity_model_selector.set(iter[Plugin::ActivityGtk::ActivityView::MODEL].children)
    end
    false
  end

  # アクティビティ更新を受け取った時の処理
  # plugin, kind, title, icon, date, service
  on_modify_activity do |params|
    next if activity_view.destroyed?
    unless mute?(params)
      params = params.dup
      case params[:icon]
      when GdkPixbuf::Pixbuf
        # TODO: Pixbufを渡された時の処理
        params[:icon] = nil
      when Diva::Model, nil, false
      # nothing to do
      else
        params[:icon] = Plugin.collect(:photo_filter, params[:icon], Pluggaloid::COLLECT).first
      end
      # FIXME: gtk3
      activity_view.scroll_to_zero_lator! if activity_view.realized? && (activity_view.vadjustment.value == 0.0)
      model = Plugin::Activity::Activity.new(params)
      next if @contains_uris.include?(model.uri.to_s)
      @contains_uris << model.uri.to_s
      iter = activity_view.model.prepend
      if model.icon
        iter[Plugin::ActivityGtk::ActivityView::ICON] = model.icon.load_pixbuf(width: 24, height: 24, &gen_icon_modifier(activity_view.model, model))
      end
      iter[Plugin::ActivityGtk::ActivityView::KIND] = model.kind
      iter[Plugin::ActivityGtk::ActivityView::TITLE] = model.title
      iter[Plugin::ActivityGtk::ActivityView::DATE] = model.created.strftime('%Y/%m/%d %H:%M:%S')
      iter[Plugin::ActivityGtk::ActivityView::MODEL] = model
      iter[Plugin::ActivityGtk::ActivityView::URI] = model.uri.to_s
      if (UserConfig[:activity_show_timeline] || []).map(&:to_s).include?(model.kind)
        Plugin.call(:update, nil, [Mikutter::System::Message.new(description: model.description, source: model.plugin_slug.to_s, created: model.created)])
      end
      if (UserConfig[:activity_show_statusbar] || []).map(&:to_s).include?(model.kind)
        Plugin.call(:gui_window_rewindstatus, Plugin::GUI::Window.instance(:default), "#{model.kind}: #{model.title}", 10)
      end
    end
  end

  onunload do
    Addon.remove_tab _('アクティビティ')
  end
end
