# Redmine - project management software
# Copyright (C) 2006-2013  Jean-Philippe Lang
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

class MessagesController < ApplicationController
  include ApplicationHelper
  # before_filter :authorize1, :only => [:show]
  menu_item :boards
  default_search_scope :messages
  before_filter :find_board, :only => [:new, :create, :preview, :edit, :update, :sticky_topic]
  before_filter :find_attachments, :only => [:preview]
  before_filter :find_message, :except => [:new, :create, :preview, :join_org_subfield, :get_subfield_on_click_org, :join_org_subfields]
  # before_filter :authorize, :except => [:preview, :edit, :update, :destroy, :message_replies, :new, :create, :join_org_subfield, :get_subfield_on_click_org, :join_org_subfields, :sticky_topic]

  helper :boards
  helper :watchers
  helper :attachments
  include AttachmentsHelper
  helper :project_score

  include CoursesHelper

  REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)

  # Show a topic and its replies
  def show
    # 顶部导航
    @project_menu_type = 3
    @topic.update_column('visits', @topic.visits + 1)
    @isReply = true
    # page = params[:page]
    # # Find the page of the requested reply
    # if params[:r] && page.nil?
    #   offset = @topic.children.count(:conditions => ["#{Message.table_name}.id < ?", params[:r].to_i])
    #   page = 1 + offset / REPLIES_PER_PAGE
    # end
    all_comments = []
    @replies = Message.where("root_id = #{@topic.id}").reorder("created_on desc")
    @reply_count = @replies.count
    @replies = get_no_children_comments_all @replies
    #@limit_count = @replies.count
    #@page = params[:page] ? params[:page].to_i + 1 : 0
    #@limit = 10
    #@replies = @replies[@page * @limit..@page * @limit + 9]
    @reply = Message.new
    if @course
      #帖子消息状态更新
      course_messages = CourseMessage.where("user_id =? and course_message_type =? and course_message_id =? and course_id =? and viewed =?", User.current.id, 'Message', @topic.id, @course.id, 0)
      course_messages.update_all(:viewed => true)
      #@replies =  @topic.children.
      #includes(:author, :attachments, :praise_tread_cache, {:board => :project}).
      #reorder("#{Message.table_name}.created_on DESC").
      #limit(@reply_pages.per_page).
      #offset(@reply_pages.offset).
      #all
      #@replies = paginateHelper messages_replies,10
      # 班级帖子回复消息设为已读

      @replies.each do |comment|
        course_message = CourseMessage.where(:course_message_type => 'Message', :course_message_id => comment.id, :user_id => User.current.id, :viewed => 0)
        course_message.update_all(:viewed => 1)
      end
      @left_nav_type = 2
      respond_to do |format|
        format.js
        format.html {render :layout => 'base_edu'}
      end
      #render :action => "show", :layout => "base_courses"#by young
    elsif @project
      #帖子消息状态更新
      project_messages = ForgeMessage.where("user_id =? and forge_message_type =? and forge_message_id =? and project_id =? and viewed =?", User.current.id, 'Message', @topic.id, @project.id, 0)
      project_messages.update_all(:viewed => true)
      #@reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
      # @replies =  @topic.children.
      #     includes(:author, :attachments, {:board => :project}).
      #     reorder("#{Message.table_name}.created_on DESC").
      #     limit(@reply_pages.per_page).
      #     offset(@reply_pages.offset).
      #     all
      # 项目帖子回复消息设为已读
      # @replies.each do |comment|
      #   project_message = ForgeMessage.where(:forge_message_type => 'Message', :forge_message_id => comment.id, :user_id => User.current.id, :viewed => 0)
      #   project_message.update_all(:viewed => 1)
      # end
      @limit_count = @replies.count
      @page = params[:page] ? params[:page].to_i + 1 : 0
      @limit = 10
      @replies = @replies[@page * @limit..@page * @limit + 9]
      respond_to do |format|
        format.js
        format.html {render :layout => 'base_projects'}
      end
    elsif @contest
      #帖子消息状态更新
      contest_messages = ContestMessage.where("user_id =? and contest_message_type =? and contest_message_id =? and contest_id =? and viewed =?", User.current.id, 'Message', @topic.id, @contest.id, 0)
      contest_messages.update_all(:viewed => true)

      # 竞赛帖子回复消息设为已读
      @replies.each do |comment|
        contest_message = ContestMessage.where(:contest_message_type => 'Message', :contest_message_id => comment.id, :user_id => User.current.id, :viewed => 0)
        contest_message.update_all(:viewed => 1)
      end
      @left_nav_type = 4
      respond_to do |format|
        format.js
        format.html { render :layout => 'base_contests' }
      end
      #render :action => "show", :layout => "base_courses"#by young
    else
      # @reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
      # @replies =  @topic.children.
      #     includes(:author, :attachments, {:board => :project}).
      #     reorder("#{Message.table_name}.created_on DESC").
      #     limit(@reply_pages.per_page).
      #     offset(@reply_pages.offset).
      #     all

      @organization = @org_subfield.organization
      respond_to do |format|
        format.js
        format.html { render :layout => 'base_org' }
      end
    end
  end

  # Create a new topic
  def new
    @message = Message.new
    if @course
      @main_board = @course.boards.where(:parent_id => 0).first
      @sub_boards = @main_board.children.reorder("position asc")
    end
    respond_to do |format|
      format.html { render :layout => 'base_edu' }
    end
  end

  def create
    if User.current.logged?
      board_id = params[:select_board_id] ? params[:select_board_id] : @board.id
      @message = Message.new
      @message.author = User.current
      @message.board_id = board_id
      @message.safe_attributes = params[:message]
      @message.sticky = params[:message][:sticky] ? 1 : 0
      if request.post?
        if @project
          is_public = @project.is_public
        elsif @course
          is_public = @course.is_public
        elsif @contest
          is_public = @contest.is_public
        end
        # 公开项目/课程上传的资源是公开的,私有项目上传的是私有的
        @message.save_attachments_containers(params[:attachments], User.current, is_public)
        if @message.save
          # 更新kindeditor上传的图片资源所有者
          if params[:asset_id]
            ids = params[:asset_id].split(',')
            update_kindeditor_assets_owner ids,@message.id,OwnerTypeHelper::MESSAGE
          end

          call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
          render_attachment_warning_if_needed(@message)
          if @course
            redirect_to board_message_url(board_id, @message)
          else
            if params[:is_board]
              if @project
                redirect_to project_boards_path(@project)
              elsif @contest
                redirect_to contest_boards_path(@contest, :board_id => @board.id)
              end
            else
              redirect_to board_message_url(board_id, @message)
            end
          end
        else
          if params[:is_board]
            if @project
              redirect_to project_boards_path(@project, :flag => true)
            elsif @course
              redirect_to course_boards_path(@course, :board_id => board_id, :flag => true)
            elsif @contest
              redirect_to contest_boards_path(@contest, :board_id => @board.id, :flag => true)
            end
          else
            layout_file = @project ? 'base_projects' : (@course ? 'base_edu' : 'base_contests')
            render :action => 'new', :layout => layout_file
          end

        end
      else
        @left_nav_type = 2
        respond_to do |format|
          format.html {
            layout_file = @project ? 'base_projects' : (@course ? 'base_edu' : 'base_contests')
            render :layout => layout_file
          }
        end
      end
    else
      redirect_to signin_path
    end
  end

  # Reply to a topic
  def reply
    if User.current.logged?
      if params[:parent_id]
        parent = Message.find params[:parent_id]
        @topic = params[:activity_id].blank? ? parent : Message.find(params[:activity_id].to_i)
        @reply = Message.new
        @reply.author = User.current
        @reply.board = parent.board
        @reply.content = params[:content]
        @reply.subject = "RE: #{@topic.subject}"
        @reply.reply_id = params[:id]
        @reply.root_id = parent.root_id.nil? ? parent.id : parent.root_id
        # @reply.reply_id = params[:id]
        parent.children << @reply
      else
        #@quote = params[:quote][:quote]
        @reply = Message.new
        @reply.author = User.current
        @reply.board = @board
        @reply.subject = @topic.subject
        @reply.content = params[:content]
        @reply.safe_attributes = params[:reply]
        #@reply.content = @quote + @reply.content
        #@reply.subject = "RE: #{@topic.subject}" unless params[:reply][:subject]
        @reply.root_id = @topic.id
        @topic.children << @reply
        # @reply.reply_id = params[:id]
      end

      update_course_activity(@topic.class,@topic.id)
      update_contest_activity(@topic.class,@topic.id)
      update_user_activity(@topic.class,@topic.id)
      update_forge_activity(@topic.class,@topic.id)
      update_org_activity(@topic.class,@topic.id)

      if @project && !params[:user_activity_id]
        redirect_to board_message_url(@board, @topic)
      else
        redirect_to message_replies_board_message_path(@topic, :board_id => @board.id, :user_activity_id => params[:user_activity_id])
      end
      #@topic.update_attribute(:updated_on, Time.now)
      # if !@reply.new_record?
      #   if params[:asset_id]
      #     ids = params[:asset_id].split(',')
      #     update_kindeditor_assets_owner ids,@reply.id,OwnerTypeHelper::MESSAGE
      #   end
      #
      #   call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
      #   attachments = Attachment.attach_files(@reply, params[:attachments])
      #   render_attachment_warning_if_needed(@reply)
      # else
      #   #render file: 'messages#show', layout: 'base_courses'
      # end

      # if params[:user_activity_id]
      #   @user_activity_id = params[:user_activity_id]
      #   @is_course = params[:is_course] if params[:is_course]
      #   @is_board = params[:is_board] if params[:is_board]
      #   respond_to do |format|
      #     format.js
      #   end
      #   return
      # else
      #   redirect_to board_message_url(@board, @topic)
      #   return
      # end
    else
      render_403
    end
  end

  def message_replies
    @replies = Message.where("root_id = #{@topic.id}").reorder("created_on desc")
    @reply_count = @replies.count
    @replies = get_no_children_comments_all @replies
    #@limit_count = @replies.count
    #@page = params[:page] ? params[:page].to_i + 1 : 0
    #@limit = 10
    #@replies = @replies[@page * @limit..@page * @limit + 9]
    @reply = Message.new()
    @user_activity_id = params[:user_activity_id].blank? ? @topic.id : params[:user_activity_id].to_i
    if !params[:user_activity_id].blank? && params[:user_activity_id].to_i != @topic.id
      @topic.update_attributes(:visits => @topic.visits + 1)
    end
    respond_to do |format|
      format.js
    end
  end

  # Edit a message
  def edit
    if @project
      (render_403; return false) unless @message.editable_by?(User.current)
    elsif @course
      (render_403; return false) unless @message.course_editable_by?(User.current)
    elsif @contest
      (render_403; return false) unless @message.contest_editable_by?(User.current)
    else
      (render_403; return false) unless @message.org_subfield_editable_by?(User.current)
    end

    respond_to do |format|
      format.html {
        if @project
          layout_file = 'base_projects'
        elsif @course
          @main_board = @course.boards.where(:parent_id => 0).first
          @sub_boards = @main_board.children.reorder("position asc")
          @left_nav_type = 2
          layout_file = 'base_edu'
        elsif @contest
          @left_nav_type = 4
          layout_file = 'base_contests'
        elsif @org_subfield
          @organization = @org_subfield.organization
          layout_file = 'base_org'
        end
        render :layout => layout_file
      }
    end
  end

  def update
    board_id = params[:select_board_id] ? params[:select_board_id] : @board.id
    @message.board_id = board_id
    @message.safe_attributes = params[:message]
    @message.sticky = params[:message][:sticky] ? 1 : 0
    if @message.save
      attachments = Attachment.attach_files(@message, params[:attachments])
      render_attachment_warning_if_needed(@message)
      #flash[:notice] = l(:notice_successful_update)
      @message.reload
      redirect_to board_message_url(board_id, @message.root, :r => (@message.parent_id && @message.id))
    end
  end

  # Delete a messages
  def destroy
    if params[:user_activity_id]
      @message.destroy
      @topic = Message.find(params[:activity_id].to_i)
      @user_activity_id = params[:user_activity_id]
      @is_course = params[:is_course] if params[:is_course]
      @is_board = params[:is_board] if params[:is_board]
      redirect_to message_replies_board_message_path(@topic, :board_id => @board.id, :user_activity_id => params[:user_activity_id])
      return
    end
    if @project
      (render_403; return false) unless @message.destroyable_by?(User.current)
    elsif @course
      (render_403; return false) unless @message.course_destroyable_by?(User.current)
    elsif @contest
      (render_403; return false) unless @message.contest_destroyable_by?(User.current)
    else
      (render_403; return false) unless @message.org_subfield_editable_by?(User.current)
    end
    r = @message.to_param
    @message.destroy
    # modify by nwb
    if @project
      if params[:is_course] && params[:is_course].to_i == 0
        redirect_to user_activities_path(User.current.id)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 0
        redirect_to project_path(@project)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 1
        redirect_to project_boards_path(@project)
      elsif @message.parent
        redirect_to board_message_url(@board, @message.parent, :r => r)
      else
        redirect_to project_board_url(@project, @board)
      end
    elsif @course
      if params[:is_course] && params[:is_course].to_i == 0
        redirect_to user_activities_path(User.current.id)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 0
        redirect_to course_path(@course)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 1
        redirect_to course_boards_path(@course)
      elsif @message.parent
        redirect_to board_message_url(@board, @message.parent, :r => r)
      else
        redirect_to course_boards_path(@course, :board_id => @board.id)
      end
    elsif @contest
      if params[:is_course] && params[:is_course].to_i == 0
        redirect_to user_contest_community_path(User.current.id)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 0
        redirect_to contest_path(@contest)
      elsif params[:is_course] && params[:is_course].to_i == 1 && params[:is_board] && params[:is_board].to_i == 1
        redirect_to contest_boards_path(@contest)
      elsif @message.parent
        redirect_to board_message_url(@board, @message.parent, :r => r)
      else
        redirect_to contest_boards_path(@contest, :board_id => @board.id)
      end
    elsif @org_subfield
      if params[:is_board]
        redirect_to organization_path(:id => @org_subfield.organization_id, :org_subfield_id => @org_subfield.id)
      else
        if @message.parent
          redirect_to board_message_url(@board, @message.parent, :r => r)
        else
          redirect_to organization_path(:id => @org_subfield.organization_id, :org_subfield_id => @org_subfield.id)
        end
      end
    end
  end

  def sticky_topic
    (render_403; return false) unless (User.current.admin? || User.current.allowed_to?(:as_teacher, @course))
    @topic.update_attributes(:sticky => @topic.sticky == 1 ? 0 : 1)
    respond_to do |format|
      format.js
      format.html{
        if params[:is_board]
          redirect_to course_boards_path(@course)
        else
          redirect_to board_message_path(@topic.board_id, @topic)
        end
      }
    end
  end

  def quote
    # @subject = @message.subject
    # @subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
    #
    # @content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
    # @temp = Message.new
    # @temp.content = "<blockquote>#{ll(Setting.default_language, :text_user_wrote, @message.author.show_name)} <br/>#{@message.content.html_safe}</blockquote>".html_safe
  end

  def preview
    message = @board.messages.find_by_id(params[:id])
    @text = (params[:message] || params[:reply])[:content]
    @previewed = message
    render :partial => 'common/preview'
  end

  def join_org_subfield
    @message = Message.find(params[:message_id])
    @organizations = User.current.organizations
  end

  def get_subfield_on_click_org
    @org = Organization.find(params[:organization_id])
  end

  def join_org_subfields
    org_subfield_ids = params[:org_subfields]
    @message = Message.find(params[:id])
    # @message.update_attribute(:updated_on, Time.now)
    # type = @message.board.course_id.nil? ? "Project":"Course"
    org_subfield_ids.each do |field_id|
      @message.quotes = @message.quotes.nil? ? 1 : (@message.quotes + 1)
      @message.save
      board = OrgSubfield.find(field_id).boards.first
      mes = Message.create(:board_id => board.id, :subject => @message.subject, :content => @message.content, :author_id => User.current.id,
                           :created_on => Time.now, :updated_on => Time.now, :locked => @message.locked, :sticky => @message.sticky)
      @message.attachments.each do |attach|
        mes.attachments << Attachment.new(:filename => attach.filename, :disk_filename => attach.disk_filename, :filesize => attach.filesize, :content_type => attach.content_type, :digest => attach.digest,
                                          :downloads => 0, :author_id => User.current.id, :created_on => Time.now, :description => attach.description, :disk_directory => attach.disk_directory, :attachtype => attach.attachtype,
                                          :is_public => attach.is_public,  :quotes => 0)
      end
      # OrgSubfieldMessage.create(:org_subfield_id => field_id.to_i, :message_id => mes.id, :message_type => type)
      # org_acts = OrgActivity.where("container_type='OrgSubfield' and container_id=? and org_act_type='Message' and org_act_id=?", field_id.to_i, @message.id)
      # if org_acts.all.size() > 0
      #   org_acts.first.update_attribute(:updated_at, Time.now)
      # else
      OrgActivity.create(:container_type => 'OrgSubfield', :container_id => field_id.to_i, :org_act_type=>'Message', :org_act_id => mes.id, :user_id => User.current.id)
      # end
    end
  end

  private
  def find_message
    return unless find_board
    @message = @board.messages.find(params[:id], :include => :parent)
    @topic = @message.root
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def find_board
    #modify by nwb
    @board = Board.find(params[:board_id])
    if @board.project_id != -1 && @board.project_id != nil
      @project = @board.project
    elsif @board.course_id && @board.course_id != -1
      @course = @board.course
    elsif @board.contest_id
      @contest = @board.contest
    else
      @org_subfield = @board.org_subfield
      @organization = @org_subfield
    end

  rescue ActiveRecord::RecordNotFound
    render_404
    nil
  end
end