require 'zip'
class ZipdownController < ApplicationController
  #查找项目（课程）
  before_filter :find_project_by_bid_id, :only => [:assort]
  #检查权限
  #勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
  SAVE_FOLDER = "#{Rails.root}/files"
  OUTPUT_FOLDER = "#{Rails.root}/tmp/archiveZip"

  #通过作业Id找到项目（课程）
  def find_project_by_bid_id
    obj_class = params[:obj_class]
    obj_id = params[:obj_id]
    obj = obj_class.constantize.find(obj_id)
    case obj.class.to_s.to_sym
      when :Bid
        @project = obj.courses[0]
    end
  end

  def assort
    if params[:obj_class] == "Bid"
      bid = Bid.find params[:obj_id]
      file_count = 0
      bid.homeworks.map { |homework| file_count += homework.attachments.count}
      if file_count > 0
        zipfile = zip_bid bid
      else
        render file: 'public/no_file_found.html'
      end
    else
      logger.error "[ZipDown#assort] ===> #{params[:obj_class]} unKown !!"
    end
    send_file zipfile, :filename => bid.name + ".zip", :type => detect_content_type(zipfile) if zipfile

  rescue Exception => e
    render file: 'public/no_file_found.html'
  end

  #下载某一学生的作业的所有文件
  def download_user_homework
    homework = HomeworkAttach.find params[:homework]
    if User.current.admin? || User.current.member_of_course?(homework.bid.courses.first)
      if homework != nil
        unless homework.attachments.empty?
          zipfile = zip_homework_by_user homework
          send_file zipfile, :filename =>  ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) +
              "_" + (homework.user.lastname.nil? ? "" : homework.user.lastname) + (homework.user.firstname.nil? ? "" : homework.user.firstname) +
              "_" + homework.name + ".zip", :type => detect_content_type(zipfile) if(zipfile)
        else
          render file: 'public/no_file_found.html'
        end
      else
        render file: 'public/file_not_found.html'
      end
    else
      render_403
    end
  rescue => e
    render file: 'public/file_not_found.html'
  end

  private

  def zip_bid(bid)
    # Todo: User Access Controll
    bid_homework_path = []
    bid.homeworks.each do |homeattach|
      unless homeattach.attachments.empty?
        bid_homework_path << zip_homework_by_user(homeattach)
      end
    end
    zipping "#{Time.now.to_i}_#{bid.name}.zip", bid_homework_path, OUTPUT_FOLDER
  end

  def zip_homework_by_user(homeattach)
    homeworks_attach_path = []
    # 需要将所有homework.attachments遍历加入zip
    # 并且返回zip路径
    homeattach.attachments.each do |attach|
      homeworks_attach_path << attach.diskfile#.to_s.slice((length+1)..-1)
    end
    zipping("#{homeattach.user.lastname}#{homeattach.user.firstname}_#{((homeattach.user.user_extensions.nil? || homeattach.user.user_extensions.student_id.nil?) ? "" : homeattach.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}.zip", homeworks_attach_path, OUTPUT_FOLDER, true)
  end


  def zipping(zip_name_refer, files_paths, output_path, is_attachment=false)
    # 输入待打包的文件列表，已经打包文件定位到ouput_path
    ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
    input_filename = files_paths

    rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip"
    zipfile_name = "#{output_path}/#{rename_zipfile}"

    Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))

    Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
      input_filename.each do |filename|
        rename_file = ic.iconv( (File.basename(filename)) ).to_s
        rename_file = ic.iconv( filename_to_real( File.basename(filename))).to_s if is_attachment

        zipfile.add(rename_file, filename)
      end
      #zipfile.get_output_stream('ReadMe') do |os|
      #  os.write 'Homeworks'
      #end
    end
    zipfile_name
  rescue Errno => e
    logger.error "[zipdown#zipping] ===> #{e}"
    @error = e
  end
  def detect_content_type(name)
    content_type = Redmine::MimeType.of(name)
    content_type.to_s
  end

  def filename_to_real(name)
    attach = Attachment.find_by_disk_filename(name)
    attach.filename
  end
end
