# root_id:nil => 主贴; 有值 => 主帖的ID(值为帖子的ID)
# parent_id: 回复(对这个id的回复)
# sticky 顶置 1
# replies_count 表示帖子的主回复(一级回复数)
# all_replies_count 表示帖子的所有回复(一级回复数 + 二级回复数)
require 'elasticsearch/model'
class Memo < ActiveRecord::Base
	include Redmine::SafeAttributes
  include UserScoreHelper
  include ApplicationHelper
  include Elasticsearch::Model
	belongs_to :forum
  has_many_kindeditor_assets :assets, :dependent => :destroy
  has_many :tidings, :as => :container , :dependent => :destroy
  belongs_to :author, :class_name => "User", :foreign_key => 'author_id'

  has_many :tag_repertoires, :through => :memo_tag_repertoires
  has_many :memo_tag_repertoires, :dependent => :destroy

	validates_presence_of :author_id, :forum_id, :subject,:content
	# 若是主题帖,则内容可以是空
	#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
	validates_length_of :subject, maximum: 100

	validate :cannot_reply_to_locked_topic, :on => :create


  #elasticsearch kaminari init
  Kaminari::Hooks.init
  Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari
  settings index: {
      number_of_shards: 5 ,
      analysis: {
          char_filter: {
              and_filter: {
                type: "mapping",
                mappings: [ "&=> and "]
             }
          },
          analyzer: {
              my_analyzer: {
                  type: 'custom',
                  tokenizer: 'standard',
                  filter: ['classic'],
                  char_filter: ['html_strip']
              }
          }
      }
  } do
    mappings dynamic: 'false' do
      indexes :subject, analyzer: 'smartcn',index_options: 'offsets'#, char_filter: 'html_strip'
      indexes :content, analyzer:'my_analyzer',index_options: 'offsets',search_analyzer: 'smartcn'
      indexes :updated_at,index:"not_analyzed" ,type:'date'
    end
  end

	acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
	acts_as_attachable
  has_many :user_score_details,  :class_name => 'UserScoreDetails',:as => :score_changeable_obj
  has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
  has_one :praise_tread_cache, as: :object, dependent: :destroy

  # 消息
  has_many :memo_messages, :class_name =>'MemoMessage', :dependent => :destroy
  # end
	belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
	# acts_as_searchable :column => ['subject', 'content'],
	# 					#:include => { :forum => :p}
	# 					#:project_key => "#{Forum.table_name}.project_id"
	# 					:date_column => "#{table_name}.created_at"
	acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
				  :datetime => :updated_at,
				  # :datetime => :created_at,
				  :description => :content,
				  :author => :author,
				  :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
				  :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
	acts_as_activity_provider :author_key => :author_id,
							  :func => 'memos',
							  :timestamp => 'created_at'
							  # :find_options => {:type => 'memos'}
	# acts_as_watchable

	safe_attributes "author_id",
					"subject",
					"content",
					"forum_id",
					"last_memo_id",
					"lock",
					"sticky",
					"parent_id",
					"replies_count",
          "all_replies_count",
          "root_id",
          "language"

	after_create :add_author_as_watcher, :reset_counters!, :send_tiding
	after_update
	after_destroy :reset_counters!,:delete_kindeditor_assets #,:down_user_score  -- 公共区发帖暂不计入得分,
	# after_create :send_notification
	# after_save :plusParentAndForum
	# after_destroy :minusParentAndForum
  #before_save :be_user_score
	# scope :visible, lambda { |*args|
	# 	includes(:forum => ).where()
	# }
  scope :indexable,lambda {
    where('parent_id is null')
  }
  scope :visible, lambda{where(hidden: 0)}
  scope :field_for_list, lambda{
    select([:id, :subject, :author_id, :sticky, :updated_at, :language, :reward, :all_replies_count, :viewed_count, :forum_id])
  }
  scope :field_for_recommend, lambda{select([:id, :subject, :language, :forum_id, :all_replies_count])}
  scope :user_posts, ->(user_id){where(root_id: nil, author_id: user_id, forum_id: [3,5])} # 只取技术分享和操作指南

  scope :memo_replies, ->(id){where(:root_id => id)}
  scope :hot, lambda{order("all_replies_count desc, updated_at desc")}
  scope :posts, lambda{ where(root_id: nil, forum_id: [3,5]) }# 只取技术分享和操作指南


  def self.search(query)
    __elasticsearch__.search(
        {
            query: {
                multi_match: {
                    query: query,
                    type:"most_fields",
                    operator: "or",
                    fields: ['subject','content^0.5']
                }
            },
            sort: {
                _score:{order: "desc" },
                updated_at:{order: "desc" }
            },
            highlight: {
                pre_tags: ['<span class="c_red">'],
                post_tags: ['</span>'],
                fields: {
                    subject: {},
                    content: {}
                }
            }
        }
    )
  end

  def reply_for_memo
    Memo.where(:parent_id => self.id)
  end

  def all_replies
    self.all_replies_count
  end

  def send_mail
      # Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
  end

  def creator_user
    self.author
  end

  def created_time
    self.created_on
  end

  def content_detail
    self.content
  end

  # 公共贴吧消息记录
  # 原则:新帖子给超级管理员发消息
  def send_tiding
    if self.parent_id.present?
      self.tidings << Tiding.new(:user_id => self.parent.author_id, :trigger_user_id => self.author_id, :parent_container_id => self.root_id, :parent_container_type => "Memo",
                                 :belong_container_id => self.forum_id, :belong_container_type => "Forum", :viewed => 0, :tiding_type => "Comment")
    else
      self.tidings << Tiding.new(:user_id => 1, :trigger_user_id => self.author_id, :parent_container_id => self.id, :parent_container_type => "Memo",
                                 :belong_container_id => self.forum_id, :belong_container_type => "Forum", :viewed => 0, :tiding_type => "Comment")
    end
  end

	def cannot_reply_to_locked_topic
		errors.add :base, l(:label_memo_locked) if root.locked? && self != root
	end

	# def update_memos_forum
	# 	if forum_id_changed?
	# 		Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
	# 		Forum.reset_counters!(forum_id_was)
	# 		Forum.reset_counters!(forum_id)
	# 	end
	# end

	def reset_counters!
		if parent && parent.id
      parent.update_attribute(:last_reply_id, parent.children.maximum(:id))
    end
    if root
      root.update_attribute(:last_reply_id, Memo.where(:root_id => root.id).maximum(:id)) unless root.destroyed?
    end
		forum.reset_counters!
	end

	def sticky?
		sticky == 1
	end

	def replies
	  Memo.where("parent_id = ?", id)
	end

	def locked?
		self.lock
	end

	def editable_by? user
		# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
		user.admin? || self.author == user
	end

	def destroyable_by? user
    (user && self.author == user) || user.admin?  || self.forum.creator == user || Memo.find(self.root_id).author == user
		#self.author == user || user.admin?
	end

	def deleted_attach_able_by? user
		(user && user.logged? && (self.author == user) ) || user.admin?
	end

	private

	def add_author_as_watcher
		Watcher.create(:watchable => self.root, :user => author)
	end

	def send_notification
		# if Setting.notified_events.include?('message_posted')
		# 	Mailer.run.message_posted(self)
		# end
  end

  # def update_reply_count
  #   if self.root_id
  #     self.root.increment!(:replies_count)
  #   end
  # end

	def plusParentAndForum
		@forum = Forum.find(self.forum_id)
		@forum.memo_count = @forum.memo_count.to_int + 1
		@forum.last_memo_id = self.id
		if self.parent_id
			@parent_memo = Memo.find_by_id(self.parent_id)
			@parent_memo.last_reply_id = self
			@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
			@parent_memo.save
		else
			@forum.topic_count = @forum.topic_count.to_int + 1
		end
		@forum.save
	end

	def minusParentAndForum
		@forum = Forum.find(self.forum_id)
		@forum.memo_count = @forum.memo_count.to_int - 1
		@forum.memo_count = 0 if @forum.memo_count.to_int < 0
		# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
		if self.parent_id
			@parent_memo = Memo.find_by_id(self.parent_id)
			# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
			@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
			@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
			@parent_memo.save
		else
			@forum.topic_count = @forum.topic_count.to_int - 1
			@forum.topic_count = 0 if @forum.topic_count.to_int < 0
		end
		@forum.save
  end

  #更新用户分数     -by zjc
  def  be_user_score
    #新建memo且无parent的为发帖
    if self.parent_id.nil?
      UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
      update_memo_number(User.current,1)

      #新建memo且有parent的为回帖
    elsif !self.parent_id.nil?
      UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
      update_replay_for_memo(User.current,1)
    end
  end

  #被删除时更新用户分数
  def down_user_score
    update_memo_number(User.current,1)
    update_replay_for_memo(User.current,1)
  end

  # Time 2015-03-26 15:20:24
  # Author lizanle
  # Description 从硬盘上删除资源
  def delete_kindeditor_assets
      delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
  end

  def create_memo_ealasticsearch_index
    if self.parent_id.nil?
      self.__elasticsearch__.index_document
    end
  end
  def update_memo_ealasticsearch_index
    if self.parent_id.nil?
        self.__elasticsearch__.update_document
    end
  end
  def delete_memo_ealasticsearch_index
    if self.parent_id.nil?
      self.__elasticsearch__.delete_document
    end
  end
end