class SiteFeedAnnc
  include Mongoid::Document
  include Mongoid::Timestamps
  UseSourceUrl = SiteFeedSetting.first.use_source_url rescue false
  field :top_list,type: Array,default: []
  field :hot_list,type: Array,default: []
  field :channel_key
  field :feed_id
  field :feed_name
  field :category_title
  field :hidden_annc,type: Array,default: []
  field :merge_with_category
  field :remote_site_url
  field :channel_title
  field :feeds_model
  field :feeds_uid_field
  field :feeds_update_callback
  field :feeds_time_field, default: "postdate"
  field :feeds_finish_callback
  field :feeds_update_statuses_callback

  has_many :site_feed_annc_details, :autosave => true, :dependent => :destroy

  def get_annc(annc_uid)
    raw_all_contents_for_feed(I18n.locale.to_s).select{|v| v['id']==annc_uid}[0] rescue {}
  end

  before_save do
    unless @skip_callback
      if self.top_list_changed? || self.hot_list_changed? || self.hidden_annc_changed? || self.category_title_changed?
        self.raw_all_contents_for_feed_translations = self.cache_annc
      end
    end
    if @raw_all_contents_for_feed_translations_changed
      self.site_feed_annc_details = []
      @raw_all_contents_for_feed_translations.each do |locale, contents|
        contents.each do |content|
          self.site_feed_annc_details << SiteFeedAnncDetail.new(
            locale: locale, site_feed_annc: self, data: content
          )
        end
      end
    end
  end
  def update_remote_site_url
    update_fields = ['source_url','source-site']
    tmp_url = self.remote_site_url
    locales = Site.first.in_use_locales rescue I18n.available_locales
    anns_translations = self.raw_all_contents_for_feed_translations
    locales.each do |l|
      anns = anns_translations[l.to_s]
      if anns
        (0...anns.count).each do |i|
          a = anns[i]
          update_fields.each do |f|
            a[f] = tmp_url
          end
          a['statuses'] = []
          if a[:is_top]
            a['statuses'] << {
              "status" => trans[locale]['top'],
              "status-class" => "status-top"
            }
          end
          if a[:is_hot]
            a['statuses'] << {
              "status" => trans[locale]['hot'],
              "status-class" => "status-hot"
            }
          end
          if !a["source-site-title"].blank?
            a['statuses'] << {
              "status" => "<a href=\"#{a["source_url"]}\" target=\"_blank\" class=\"feed-source\">#{a["source-site-title"]}</a>",
              "status-class" => "status-source"
            }
          end
        end
      end
    end
    self.raw_all_contents_for_feed_translations = anns_translations
    self.save
  end
  def update_channel_title(update_url=false) #update_url=true will also fix remote_site_url in data
    update_fields = []
    if update_url
      update_fields = ['source_url','source-site']
    end
    tmp_url = self.remote_site_url
    locales = Site.first.in_use_locales rescue I18n.available_locales
    trans = {}
    locales.each do |locale|
      locale = locale.to_s
      trans[locale] = {}
      I18n.with_locale(locale) do
        trans[locale]['top'] = I18n.t(:top)
        trans[locale]['hot'] = I18n.t(:hot)
        trans[locale]['more_plus'] = I18n.t("feed.more")
      end
    end
    anns_translations = self.raw_all_contents_for_feed_translations
    locales.each do |locale|
      source_site_title = (self[:channel_title][locale] rescue "")
      anns = anns_translations[locale]
      if anns
        (0...anns.count).each do |i|
          a = anns[i]
          a["source-site-title"] = source_site_title
          update_fields.each do |f|
            a[f] = tmp_url
          end
          a['statuses'] = []
          if a[:is_top]
            a['statuses'] << {
              "status" => trans[locale]['top'],
              "status-class" => "status-top"
            }
          end
          if a[:is_hot]
            a['statuses'] << {
              "status" => trans[locale]['hot'],
              "status-class" => "status-hot"
            }
          end
          if !a["source-site-title"].blank?
            a['statuses'] << {
              "status" => "<a href=\"#{a["source_url"]}\" target=\"_blank\" class=\"feed-source\">#{a["source-site-title"]}</a>",
              "status-class" => "status-source"
            }
          end
        end
      end
    end
    self.raw_all_contents_for_feed_translations = anns_translations
    self.save
  end
  def process_tmp(site, a, locale=nil, trans=nil, site_root_url=nil)
    cat = self[:category_title]
    locale = I18n.locale.to_s if locale.nil?
    if trans.nil?
      trans = {}
      locales.each do |locale|
        locale = locale.to_s
        trans[locale] = {}
        I18n.with_locale(locale) do
          trans[locale]['top'] = I18n.t(:top)
          trans[locale]['hot'] = I18n.t(:hot)
          trans[locale]['more_plus'] = I18n.t("feed.more")
        end
      end
    end
    if site_root_url.nil?
      site_root_url = site.root_url
    end
    tmp = a.deep_dup
    if self.channel_key == "announcement"
      files = tmp["bulletin_files"].collect{|bf| { "file_url" => bf["url"], "file_title" => (bf["title_translations"][locale].blank? ? File.basename(bf["url"]) : bf["title_translations"][locale] rescue '') }} rescue []
      links = tmp["bulletin_links"].map{|link|  { "link_url" => link["url"], "link_title" => (link["title_translations"][locale].blank? ? link["url"] : link["title_translations"][locale]) } } rescue []
      tmp["bulletin_links"] = links
      tmp["bulletin_files"] = files
      tmp["title"] = tmp["title_translations"][locale]

      tmp["subtitle"] = tmp["subtitle_translations"][locale]
      tmp["link_to_show"] = !tmp["external_link"].blank? ? tmp["external_link"] : nil
      tmp["img_src"] = tmp["image"]["thumb"] || "/assets/announcement-default.jpg"
      tmp["img_src"] = "/assets/announcement-default.jpg" if tmp["img_src"] == ""
      tmp["img_description"] = tmp["image_description_translations"][locale]
    else
      new_tmp = {}
      tmp.each do |key,value|
        key = key.to_s
        if key.include? "_translations"
          new_tmp[key] = value
          new_tmp[key.sub("_translations","")] = value[locale].to_s rescue ""
        elsif key.include?("date") || key.include?("Date")
          new_tmp[key] = DateTime.parse(value) rescue nil
        else
          if value.class == Hash
            new_tmp[key] = {}
            value.each do |sub_k,sub_v|
              if sub_k.include? "_translations"
                new_tmp[key][sub_k] = sub_v
                new_tmp[key][sub_k.sub("_translations","")] = sub_v[locale].to_s rescue ""
              else
                new_tmp[key][sub_k] = sub_v
              end
            end
          else
            new_tmp[key] = value
          end
        end
      end
      tmp = BSON::Document.new(new_tmp)
    end

    if !tmp["title"].blank?
      tmp["title_plain_text"] = Nokogiri::HTML5.fragment(tmp["title"]).text
    end

    tmp["category"] = cat

    tmp["target"] = (
      tmp["link_to_show"].blank? || (!site_root_url.blank? && tmp["link_to_show"].include?(site_root_url))
    ) ? '_self' : '_blank'

    tmp["params"] = tmp["params"].to_s + "_" + self.feed_id.to_s + "h"
    tmp["more"] = trans[locale]['more_plus']
    tmp["view_count"] = ""


    tmp['statuses'] = []
    if self.top_list.exclude?(tmp['id'])
      tmp["is_top"] = false
    else
      tmp["is_top"] = true
      tmp['statuses'] << {
        "status" => trans[locale]['top'],
        "status-class" => "status-top"
      }
    end
    if self.hot_list.exclude?(tmp['id'])
      tmp["is_hot"] = false
    else
      tmp["is_hot"] = true
      tmp['statuses'] << {
        "status" => trans[locale]['hot'],
        "status-class" => "status-hot"
      }
    end

    tmp["is_hidden"] = self.hidden_annc.include?(tmp['id'])

    tmp["source_url"] = self.remote_site_url
    tmp["source-site"] = self.remote_site_url
    tmp["source-site-title"] = self.channel_title(locale)


    if !tmp["link_to_show"].blank? && tmp["link_to_show"].start_with?("/")
        tmp["link_to_show"] = "#{tmp["source_url"]}#{tmp["link_to_show"]}"
    end
    

    if !tmp["source-site-title"].blank?
      tmp['statuses'] << {
        "status" => "<a href=\"#{tmp["source-site"]}\" target=\"_blank\" class=\"feed-source\">#{tmp["source-site-title"]}</a>",
        "status-class" => "status-source"
      }
    end

    tmp["source-site-link"] = tmp["source-site"]
    tmp["source-site"] = "<a href=\"#{tmp["source-site"]}\" target=\"_blank\" class=\"feed-source\">#{tmp["source-site-title"]}</a>"

    feeds_time_fields = Array(self.feeds_time_field)
    feeds_time_fields.each do |feeds_time_field|
      time_field_value = tmp[feeds_time_field]
      tmp[feeds_time_field] = (time_field_value.blank? ? nil : time_field_value.to_time rescue time_field_value)
      tmp[feeds_time_field] = time_field_value if tmp[feeds_time_field].nil?
    end
    return tmp
  end
  def cache_annc(force_refresh=false,locales=nil,trans=nil)
    feed = SiteFeed.find(self.feed_id)
    anns = feed.get_annc(force_refresh)
    site = Site.first
    if locales.nil?
      locales = site.in_use_locales rescue I18n.available_locales
    end
    if trans.nil?
      trans = {}
      locales.each do |locale|
        locale = locale.to_s
        trans[locale] = {}
        I18n.with_locale(locale) do
          trans[locale]['top'] = I18n.t(:top)
          trans[locale]['hot'] = I18n.t(:hot)
          trans[locale]['more_plus'] = I18n.t("feed.more")
        end
      end
    end
    cache_data = {}
    site_root_url = site.root_url rescue ""
    locales.each do |locale|
      locale = locale.to_s
      data_for_locale = anns.collect do |a|
        tmp = process_tmp(site, a, locale, trans, site_root_url)
      end
      cache_data[locale.to_s] = data_for_locale
    end
    cache_data
  end

  def self.add_prefix(match_cond)
    case match_cond
    when Array
      match_cond = match_cond.collect do |val|
        self.add_prefix(val)
      end
    when Hash
      match_cond = match_cond.inject({}) do |m, (key, val)|
        if val.class == Hash || (val.class == Array && val[0].class == Hash)
          val = self.add_prefix(val)
        end
        if !key.start_with?("$")
          key = "data.#{key}"
        end
        m[key] = val
        m
      end
    end
    return match_cond
  end

  def self.get_feed_cache(
    channel_key,merge_with_category=nil,
    site_source=nil,locale=I18n.locale.to_s,
    is_widget=false,max_len=nil,sort_maps=nil,extra_match_cond=nil
  )
    locale = I18n.locale.to_s
    max_len = max_len.to_i
    module_app = ModuleApp.where(:key=>channel_key).first
    feeds_time_field = module_app.feeds_time_field rescue nil
    if feeds_time_field.nil?
      feeds_time_field = 'postdate'
    end
    feeds_time_fields = Array(feeds_time_field)
    site_feed_anncs = self.where("channel_key" => channel_key)
    if !merge_with_category.blank? && merge_with_category.exclude?('all')
      site_feed_anncs = site_feed_anncs.where(:merge_with_category.in => merge_with_category)
    end
    if site_source
      site_feed_anncs = site_feed_anncs.where({"channel_title.#{locale}" => site_source})
    end
    site_feed_annc_ids = site_feed_anncs.pluck(:id)
    match_cond = {
      "site_feed_annc_id" => {"$in" => site_feed_annc_ids},
      "locale" => locale
    }

    if extra_match_cond
      match_cond = match_cond.merge(add_prefix(extra_match_cond))
    end

    pipeline = [
      {"$match" => match_cond},
      {"$project"=>{"data"=>1}}
    ]
    
    pipeline_to_get_data = pipeline.clone

    if sort_maps
      sort_maps = sort_maps.collect do |sort_key, sort_val|
        ["data.#{sort_key}", sort_val == :desc ? -1 : 1]
      end.to_h
      pipeline_to_get_data << {"$sort"=>sort_maps}
    end

    if max_len > 0
      pipeline_to_get_data << {"$limit"=> max_len}
    end

    pipeline_to_get_count = pipeline.clone
    pipeline_to_get_count << {"$group" => {
      _id: nil,
      count: {"$sum" => 1}
    }}

    count_result = SiteFeedAnncDetail.collection.aggregate(pipeline_to_get_count).first
    feeds_count = count_result ? count_result["count"] : 0


    feeds = SiteFeedAnncDetail.collection.aggregate(pipeline_to_get_data).collect do |data|
      tmp = data['data']
      if !(tmp['category'].is_a? String)
        tmp['category'] = tmp['category'][locale]
      end
      if @image_version != 'thumb' && !@image_version.nil?
        if @image_version == 'mobile'
          tmp["img_src"] = tmp["image"]["mobile"]
        else
          tmp["img_src"] = tmp["image"]["original"]
        end
        tmp["img_src"] = tmp["img_src"] || "/assets/announcement-default.jpg"
      end
      if tmp["link_to_show"].nil?
        tmp["link_to_show"] = UseSourceUrl && tmp["show_url"] ?
          "#{tmp["source_url"]}/#{locale}#{tmp["show_url"]}" :
          is_widget ? OrbitHelper.widget_item_url(tmp["params"]) : OrbitHelper.url_to_show(tmp["params"])
      end
      tmp
    end
    return feeds, feeds_count
  end

  # @deprecated Please use {#get_feed_cache} instead
  def all_contents_for_feed(site_source=nil,locale=I18n.locale.to_s,is_widget=false)
    if !site_source.nil? && site_source != self[:channel_title][locale]
      return []
    end
    time_now = Time.now
    self.raw_all_contents_for_feed(locale.to_s).collect do |v|
      tmp = v
      next if tmp["is_hidden"]  || (!tmp["postdate"].nil? && tmp["postdate"]<Time.now) || tmp['title'].blank?
      tmp['category'] = tmp['category'][locale]
      if @image_version != 'thumb' && !@image_version.nil?
        if @image_version == 'mobile'
          tmp["img_src"] = tmp["image"]["mobile"]
        else
          tmp["img_src"] = tmp["image"]["original"]
        end
        tmp["img_src"] = tmp["img_src"] || "/assets/announcement-default.jpg"
      end
      if tmp["link_to_show"].nil?
        if !is_widget
          tmp["link_to_show"] = UseSourceUrl && tmp["show_url"] ? "#{tmp["source_url"]}/#{locale}#{tmp["show_url"]}" : OrbitHelper.url_to_show(tmp["params"]) rescue ''
        else
          tmp["link_to_show"] = UseSourceUrl && tmp["show_url"] ? "#{tmp["source_url"]}/#{locale}#{tmp["show_url"]}" : OrbitHelper.widget_item_url(tmp["params"]) rescue ''
        end
      end
      tmp
    end.compact
  end

  def raw_all_contents_for_feed(locale)
    SiteFeedAnncDetail.where(site_feed_annc: self, locale: locale).collect{|detail| 
      detail.data
    }
  end

  def raw_all_contents_for_feed_translations
    (@raw_all_contents_for_feed_translations ||= SiteFeedAnncDetail.where(site_feed_annc: self).group_by{|detail| 
      detail.locale
    }.transform_values do |details|
      details.collect{|detail| detail.data}
    end).deep_dup
  end

  def raw_all_contents_for_feed_translations=(translations)
    if raw_all_contents_for_feed_translations != translations
      @raw_all_contents_for_feed_translations_changed = true
      @raw_all_contents_for_feed_translations = translations
    end
  end

  def channel_title(locale=I18n.locale)
    self[:channel_title][locale] rescue self[:channel_title]
  end
  def category
    Category.find(self.merge_with_category) rescue nil
  end
  def category_title
    self[:category_title][I18n.locale.to_s]
  end
end