#encoding=utf-8
class ContestsController < ApplicationController

  include ContestsHelper
  helper :contest_members
  helper :users
  helper :attachments
  helper :files
  include AvatarHelper
  include ApplicationHelper
  
  before_filter :find_contest, :only => [:show, :settings, :update, :destroy, :contest_activities, :private_or_public, :switch_role, :set_invite_code_halt, :renew,
                                            :member, :export_all_members, :feedback]
  before_filter :is_logged, :only => [:index, :new, :create]
  before_filter :is_admin?, :only => [:settings, :set_invite_code_halt, :destroy]
  before_filter :is_member?, :only => [:show, :contest_activities]

  layout "base_contests"

  def show
    #更新创建课程消息状态
    update_messsages_to_viewed("ContestMessage", @contest)
    @left_nav_type = 1

    contest_activities = @contest.contest_activities
    @page = params[:page] ? params[:page].to_i + 1 : 0
    if params[:type].present?
      case params[:type]
        when "work"
          @contest_activities = contest_activities.where("contest_act_type = 'Work'").order('updated_at desc')
        when "news"
          @contest_activities = contest_activities.where("contest_act_type = 'News'").order('updated_at desc')
        when "message"
          @contest_activities = contest_activities.where("contest_act_type = 'Message'").order('updated_at desc')
        when "poll"
          @contest_activities = contest_activities.where("contest_act_type = 'Poll'").order('updated_at desc')
        when "attachment"
          @contest_activities = contest_activities.where("contest_act_type = 'Attachment'").order('updated_at desc')
        when "journalsForMessage"
          @contest_activities = contest_activities.where("contest_act_type = 'JournalsForMessage'").order('updated_at desc')
        when "news"
          @contest_activities = contest_activities.where("contest_act_type = 'News'").order('updated_at desc')
        else
          @contest_activities = contest_activities.order('updated_at desc')
      end
    else
      @contest_activities = contest_activities.order('updated_at desc')
    end
    @contest_activities_count = @contest_activities.count
    @contest_activities = @contest_activities.limit(10).offset(@page * 10)
    @type = params[:type]

    respond_to do |format|
      format.js
      format.html
    end
  end

  def contest_activities
    contest_activities = @contest.contest_activities
    @page = params[:page] ? params[:page].to_i + 1 : 0
    if params[:type].present?
      case params[:type]
        when "work"
          @contest_activities = contest_activities.where("contest_act_type = 'Work'").order('updated_at desc')
        when "news"
          @contest_activities = contest_activities.where("contest_act_type = 'News'").order('updated_at desc')
        when "message"
          @contest_activities = contest_activities.where("contest_act_type = 'Message'").order('updated_at desc')
        when "poll"
          @contest_activities = contest_activities.where("contest_act_type = 'Poll'").order('updated_at desc')
        when "attachment"
          @contest_activities = contest_activities.where("contest_act_type = 'Attachment'").order('updated_at desc')
        when "journalsForMessage"
          @contest_activities = contest_activities.where("contest_act_type = 'JournalsForMessage'").order('updated_at desc')
        when "news"
          @contest_activities = contest_activities.where("contest_act_type = 'News'").order('updated_at desc')
        else
          @contest_activities = contest_activities.order('updated_at desc')
      end
    else
      @contest_activities = contest_activities.order('updated_at desc')
    end
    @contest_activities_count = @contest_activities.count
    @contest_activities = @contest_activities.limit(10).offset(@page * 10)
    @type = params[:type]

    @left_nav_type = 2
    respond_to do |format|
      format.js
      format.html
      format.api
    end
  end

  def new
    if User.current.login?
      @contest = Contest.new
      render :layout => 'new_base'
    else
      redirect_to signin_url
    end
  end

  def create
    @contest = Contest.new
    @contest.name = params[:contest][:name]
    params[:contest][:is_public] ? @contest.is_public = 1 : @contest.is_public = 0
    @contest.user_id = User.current.id
    if @contest && @contest.save
      #unless User.current.admin?
      member = ContestMember.new(:user_id => User.current.id)

      @contest.contest_members << member
      ContestMemberRole.create(:contest_member_id => member.id, :role_id => 13)

      @contest.contest_acts << ContestActivity.new(:user_id => @contest.user_id,:contest_id => @contest.id)
      respond_to do |format|
        format.html {redirect_to contest_url(@contest)}
      end
    end
  end

  def update
    @contest.name = params[:contest][:name]
    @contest.description = params[:contest][:description]
    # @project.organization_id = params[:organization_id]
    params[:contest][:is_public] == "on" ? @contest.is_public = 1 : @contest.is_public = 0
    @contest.save_attachments(params[:attachments])
    begin
      if @contest.save
        respond_to do |format|
          format.html{redirect_to contest_path(@contest)}
        end
      end
    rescue Exception => e
      @message = e.message
    end
  end

  def destroy
    @contest.update_attributes(:is_delete => true)
  end

  def feedback
    if (User.current.admin? || @contest.is_public || (!@contest.is_public && User.current.member_of_contest?(@contest)))
      ContestMessage.where(:user_id => User.current.id, :contest_id => @contest.id, :contest_message_type => 'JournalsForMessage', :contest_message_id => @contest.journals_for_messages.map{|jour|jour.id}).update_all(:viewed => true)
      page = params[:page]
      # Find the page of the requested reply
      @jours = @contest.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
      @jour_count = @jours.count
      @limit =  10
      if params[:r] && page.nil?
        offset = @jours.count(:conditions => ["#{JournalsForMessage.table_name}.id > ?", params[:r].to_i])
        page = 1 + offset / @limit
      end
      @jour = paginateHelper @jours,10
      @state = false
      @left_nav_type = 6
      respond_to do |format|
        format.html{render :layout => 'base_contests'}
        format.api
      end
    else
      render_403
    end
  end

  def private_or_public
    @contest.update_attributes(:is_public => !@contest.is_public)

    respond_to do |format|
      format.js
    end
  end

  #设置竞赛公开或私有
  def set_contest_attribute
    contest_id = params[:contest].to_i
    @contest = Contest.find(contest_id)
    @user = User.find(params[:user_id])
    @contest.is_public? ?  @contest.update_attribute(:is_public, false) : @contest.update_attribute(:is_public, true)
    respond_to do |format|
      format.js
    end
  end

  def settings
    @select_tab = params[:tab]

    @member ||= @contest.contest_members.new
    @roles = Role.where("id in (13, 14, 15)")
    @members = @contest.member_principals.includes(:roles, :principal).all.sort
  end

  def join_contest

  end

  def join_contest_multi_role
    if User.current.logged?
      cs = ContestsService.new
      @user = User.current
      join = cs.join_contest_roles params,@user
      @state = join[:state]
      @contest = join[:contest]
    else
      @state = 5 #未登录
    end
    @object_id = @contest.id if @contest
    respond_to do |format|
      format.js
    end
  end

  #处理加入竞赛成为管理员、评委、参赛者的请求
  #status 1 同意 2 拒绝
  def dealwith_apply_request
    @msg = AppliedMessage.find(params[:msg_id])
    #AppliedMessage role  13 管理员 14 评委 15 参赛者
    applied_contest = @msg.applied
    apply_user = User.find(applied_contest.user_id)
    ids = applied_contest.role.split(",") #  [@msg.content] msg content保存的是申请的职位角色
    integer_ids = []
    ids.each do |role_id|
      integer_ids << role_id.to_i
    end
    case params[:agree]
      when 'Y'
        if ContestMember.where(:user_id => apply_user.id, :contest_id => applied_contest.contest_id).first.nil?
          member = ContestMember.new(:user_id => apply_user.id)
          Contest.find(applied_contest.contest_id).contest_members << member
        else
          member = ContestMember.where(:user_id => apply_user.id, :contest_id => applied_contest.contest_id).first
        end

        contest_member_roles = member.contest_member_roles
        if integer_ids.include?(14) && integer_ids.include?(13)
          contest_member_roles << ContestMemberRole.new(:role_id => 13)
          contest_member_roles << ContestMemberRole.new(:role_id => 14, :is_current => 0)
        else
          contest_member_roles << ContestMemberRole.new(:role_id => integer_ids[0])
        end

        ContestMessage.create(:user_id => apply_user.id, :contest_id => applied_contest.contest_id, :viewed => false,:contest_message_id=>User.current.id,:content=>applied_contest.role,:contest_message_type=>'ContestRequestDealResult',:status=>1)
        applied_contest.applied_messages.update_all(:status => 1, :viewed => 1, :applied_user_id => User.current.id)
        @msg.update_attributes(:status => 1, :viewed => 1, :applied_user_id => User.current.id)
        applied_contest.update_attributes(:status => 1)
        if integer_ids.include?(15)
          ContestantForContest.create(:student_id => apply_user.id, :contest_id =>applied_contest.contest_id)
        end

      when 'N'
        ContestMessage.create(:user_id => apply_user.id, :contest_id => applied_contest.contest_id, :viewed => false,:contest_message_id=>User.current.id,:content=>applied_contest.role,:contest_message_type=>'ContestRequestDealResult',:status=>2)
        applied_contest.applied_messages.update_all(:status => 2, :viewed => 1, :applied_user_id => User.current.id)
        @msg.update_attributes(:status => 2, :viewed => 1, :applied_user_id => User.current.id)
        applied_contest.update_attributes(:status => 2)
    end
    respond_to do |format|
      format.js
    end
  end

  def switch_role
    members = @contest.contest_members.where("user_id = #{params[:user_id]}")
    unless members.blank?
      curr_role = ContestMemberRole.find_by_contest_member_id_and_role_id(members.first.id, params[:curr_role])
      tar_role = ContestMemberRole.find_by_contest_member_id_and_role_id(members.first.id, params[:tar_role])
      unless (curr_role.nil? || tar_role.nil?)
        curr_role.update_column('is_current', 0)
        tar_role.update_column('is_current', 1)
      end
    end
    redirect_to contest_path(@contest)
  end

  # 邀请码停用/启用
  def set_invite_code_halt
    if User.current.admin_of_contest?(@contest) || User.current.admin?
      @contest.update_attribute('invite_code_halt', @contest.invite_code_halt == 0 ? 1 : 0)
    end
  end

  # 恢复已删除的竞赛
  def renew
    if User.current.admin?
      @contest.update_attributes(:is_delete => false)
      respond_to do |format|
        format.js
      end
    else
      return 404
    end
  end

  # 成员列表
  def member
    if (User.current.admin? || @contest.is_public || (!@contest.is_public && User.current.member_of_contest?(@contest)))
      @role = params[:role].nil? ? '3' : params[:role]
      case @role
        when '1'
          @members = contest_managers @contest
        when '2'
          @members = contest_judges @contest
        when '3'
          @members = contest_contestants @contest
      end
      if params[:name]
        q = "#{params[:name].strip}"
        @members = search_member_by_name_login_school @members, q
      end
      @limit = 50
      @page = params[:page].nil? ? 1 : params['page'].to_i
      @members_count = @members.count
      @mem_pages = Paginator.new @members_count, @limit, @page
      @members = paginateHelper @members, @limit
      respond_to do |format|
        format.html {render :layout => 'base_contests'}
        format.js
      end
    else
      render_403
    end
  end

  def export_all_members
    sql = "SELECT DISTINCT(cmr.id) AS cmr_id, cmr.role_id, users.`login`, users.id AS user_id, users.`mail`, cmr.created_at FROM users, contest_members cm, contest_member_roles cmr, user_extensions ue, schools " +
          "WHERE users.id = cm.`user_id` AND users.id=ue.`user_id` AND cmr.`contest_member_id` = cm.`id` AND cm.`contest_id` = #{@contest.id} AND (ue.`school_id` IS NULL OR ue.`school_id` = schools.`id`) " +
          "ORDER BY role_id ASC, CONVERT(schools.`name` USING gbk) COLLATE gbk_chinese_ci DESC, CONVERT(users.`lastname` USING gbk) COLLATE gbk_chinese_ci DESC"
    @members = ContestMemberRole.find_by_sql sql
    respond_to do |format|
      format.xls {
        filename = "#{@contest.name.to_s}-成员列表-#{DateTime.parse(Time.now.to_s).strftime('%Y%m%d%H%M%S').to_s}.xls"
        send_data(member_to_xls(@members), :type => "text/excel;charset=utf-8; header=present",
                  :filename => filename_for_content_disposition("#{filename}.xls"))
      }
    end
  end

  private

  def  member_to_xls members
    xls_report = StringIO.new
    book = Spreadsheet::Workbook.new
    sheet1 = book.create_worksheet :name => "成员列表"
    blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10
    #sheet1.row(0).default_format = blue
    #sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_class),l(:excel_f_score),l(:excel_commit_time)])
    sheet1[0,0] = "id"
    sheet1[0,1] = "姓名"
    sheet1[0,2] = "登录名"
    sheet1[0,3] = "电子邮箱"
    sheet1[0,4] = "单位"
    sheet1[0,5] = "角色"
    sheet1[0,6] = "加入时间"
    count_row = 1
    members.each_with_index do |member, i|
      user = User.find(member.user_id)
      sheet1[count_row,0]= user.id
      sheet1[count_row,1] = user.show_name
      sheet1[count_row,2] = user.login
      sheet1[count_row,3] = user.mail
      sheet1[count_row,4] = user.user_extensions.school_id.blank? ? "" : (user.user_extensions.school.blank? ? "" : user.user_extensions.school.name)
      sheet1[count_row,5] = member.role_id == 13 ? "管理员" : (member.role_id == 14 ? "评委" : "参赛者")
      sheet1[count_row,6] = format_time member.created_at
      count_row += 1
    end
    book.write xls_report
    xls_report.string
  end

  def find_contest
    if params[:id].to_i < 780
      render_403
      return
    end
    @contest = Contest.find(params[:id])
    if @contest.is_delete and !User.current.admin?
      render_404
      return
    end
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def is_logged
    redirect_to signin_path unless User.current.logged?
  end

  def is_admin?
    unless User.current.admin_of_contest?(@contest) || User.current.admin?
      render_403
      return
    end
  end

  def is_member?
    if User.current.member_of_contest?(@contest) || User.current.admin? || @contest.is_public

    else
      render_403
      return
    end
  end
end