require 'rubygems'
require 'zip'
require 'net/http'
require 'net/scp'
require 'open-uri'

class DownloadsController < ApplicationController

  layout 'simple'

  def index
    unless params[:ids].blank?
      if params[:offre]
        params[:ids] = []
        ReportagePhoto.where(reportage_id: params[:offre].to_i).collect{|p| params[:ids] << Image.find_by_ms_image_id(p.photo_ms_id).id}
      end
      params[:ids].delete_if { |i| i==''}
      params[:ids].uniq!
      if !params[:ids].blank?
        u = current_user
        if params[:definition] == 'HD'
          @aff_txt = ''
          ids_hdl = []
          ids_mov = []
          ids_dem = []
          ids_del = []
          ids_remote_access = []
          params[:ids].each do |im|
            im_found = Image.find(im)
            if im_found.nil? || !session[:provs].include?(im_found.provider_id)
              ids_del << im
            elsif (session[:provhd][im_found.provider_id] != 1) || (im_found.ms_id == 'embed') || (im_found.hires_location == '')
              ids_dem << im
              ids_del << im
              @aff_txt += "#{im_found.original_filename} : demande envoyée<br>"
            elsif im_found.provider.local
              unless im_found.provider.input_dir.blank?
                @local_name = im_found.provider.name
                ids_hdl << im
                ids_del << im
              end
            elsif im_found.ms_id == 'mp4'
              ids_remote_access << im
              ids_del << im
              @remote_url = im_found.hires_location
              @aff_txt += 'Redirection vers la vidéo HD en cours... <br>'
            else
              @aff_txt += "#{im_found.original_filename} : photo haute définition téléchargée"
              @aff_txt += "<span style='color:red;font-size:15px;font-style:italic'> (attention haute résolution inférieure à 200 Ko)</span>" unless (im_found.hr_size > 204800 or im_found.hr_size <= 0)
              @aff_txt += '<br>'
            end
          end
          ids_del.each do |i|
            params[:ids].delete(i)
          end

          if ids_hdl.empty?
            if conditions
              render :has_conditions, layout: nil
            else
              params[:ids].each{|i| Statistic.create(user_id: u.id, image_id: i, operation_label_id: 2)}
              @dwn = marek_download_request(*params[:ids])
              render :index, layout: nil
              mov_hd_download(ids_mov) unless ids_mov.empty?
              remote_access(ids_remote_access,'HD') unless ids_remote_access.empty?
              demande_download(ids_dem, 'HD') unless ids_dem.empty?
              params[:operation] = 'HD'
            end
          elsif params[:ids].empty?
            local_download(ids_hdl, 'HD', 'hires')
          else
            @ids_hd = params[:ids]
            @ids_lhd = ids_hdl
            render :double_download, layout: nil
          end

        elsif params[:definition] == 'BD'
          @aff_txt = ''
          ids_dem = []
          ids_del = []
          ids_remote_access = []
          ids_remote_download = []
          params[:ids].each do |im|
            im_found = Image.find(im)
            if im_found.nil?
              ids_del << im
            elsif (session[:provbd][im_found.provider_id] != 1) || (im_found.ms_id == 'embed') || (im_found.ms_id == 'mp4' and  !["Pond5","Ash"].include?(im_found.provider.string_key)) || (im_found.medium_location == '')
              ids_dem << im
              ids_del << im
              @aff_txt += "#{im_found.original_filename} : demande envoyée"
            elsif im_found.ms_id == 'flv' || (im_found.ms_id == 'mp4' && im_found.provider.string_key == 'Ash')
              ids_remote_download << im
              ids_del << im
              @aff_txt += "#{im_found.original_filename} : vidéo basse définition téléchargée"
            elsif im_found.provider.string_key=='Pond5'
              ids_remote_access << im
              ids_del << im
              @remote_url = im_found.hires_location
              @aff_txt += 'Redirection vers la vidéo en cours... <br>'
            else
              @aff_txt += "#{im_found.original_filename} : photo basse définition téléchargée"
            end
          end
          ids_del.each do |i|
            params[:ids].delete(i)
          end
          render :index, layout: nil
          local_download(params[:ids], 'BD', 'medium') unless params[:ids].empty?
          remote_download(ids_remote_download, 'BD', 'medium') unless ids_remote_download.empty?
          remote_access(ids_remote_access,'BD') unless ids_remote_access.empty?
          demande_download(ids_dem, 'BD') unless ids_dem.empty?
        elsif params[:definition] == 'FLUX'
          flux_download(dwn_path, *params[:ids])
        elsif params[:definition] == 'LHD'
          local_download(params[:ids], 'HD', 'hires')
        end
      end
    end
  end

  def conditions
    return false if params[:condition_checked]
    prov = params[:ids].collect{ |i| Image.find(i).provider_id unless Image.find(i).provider.provider_conditions.blank? }
    @cond = {}
    session[:bnf_files] = []
    params[:ids].each do |i|
      p = Image.find(i).provider_id
      if Provider.find(p).string_key == 'Bnf'
        session[:bnf_files] << Image.find(i).original_filename
        prov << p
      end
      @cond[p]= [] unless @cond.key? p
      @cond[p] << i
    end
    prov.compact!
    return false if prov.blank?
    @prov = prov.uniq
    true
  end


  def bnf_form
    parameters = {
        :legal_name           => params[:legal_name],
        :contact_name         => params[:contact_name],
        :contact_email        => params[:contact_email],
        :adresse              => params[:adresse],
        :postal_code          => params[:postal_code],
        :city                 => params[:city],
        :pays                 => params[:pays],
        :project_title        => params[:project_title],
        :project_author       => params[:project_author],
        :publication_date     => params[:publication_date],
        :diffusion            => params[:diffusion],
        :page_inter_vign      => params[:page_inter_vign],
        :page_inter           => params[:page_inter],
        :couv                 => params[:couv],
        :television           => params[:television],
        :webdoc               => params[:webdoc],
        :cd_dvd_vod           => params[:cd_dvd_vod],
        :cinema               => params[:cinema],
        :web                  => params[:web],
        :expo                 => params[:expo],
        :redevance            => params[:redevance],
        :other                => params[:other],
        :bnf_files            => session[:bnf_files]
    }
    session[:bnf_files].collect do |f|
      parameters[:bnf_files] = f
      api_call('bnf_form', current_user.login, 0, parameters)
    end
    flash[:notice] =  I18n.t('download_conditions.mail_ok')
    render 'error', layout: nil
  end

  def show
    respond_to do |format|
      format.xml { render :xml => 'ok'}
    end
  end

  def bnf_mail
    provider= Provider.find_by_name('Bnf')
    mail_to = provider.provider_contacts.find_by_receive_requests(true).email
    user = User.find_by_login(params[:login])
    mail = UserMailer.send_bnf_form(mail_to, params[:parameters], user).deliver_now
    respond_to do |format|
      format.json { render json: {} }
    end
  end

  #To Do : check if still used if not delete
  def user_demand
    img = Image.find_by_ms_image_id(params[:ms_id].to_i)
    unless img.nil?
      user = User.find_by_login(params[:login])
      prov = Provider.where(id: img.provider_id).select(:name, :string_key).first
      p_name = prov.name
      mel = ProviderContact.where(provider_id: img.provider_id, receive_demand: true).collect{|pc| pc.email}
      img_creator = prov.is_pixtech_stock? ? img.creator : ''
      UserMailer.dw_provider(img.original_filename, img.thumb_location, img_creator, p_name, mel, user, params[:operation]).deliver_now
      UserMailer.dw_user(img.original_filename, img.thumb_location, p_name, mel, user, params[:operation]).deliver_now
    end
    respond_to do |format|
      format.json { render json: {} }
    end
  end

  def mov_hd_download(ids)
    parameters = { :type_op => 'video'}
    ids.each do |i|
      Statistic.create_stat(current_user.id, i, 4)
      img = Image.find(i)
      im_id << img.ms_image_id
      api_call('img_demand', current_user.login, img.ms_image_id, parameters)
      #Delayed::Job.enqueue ForwardCsRequest.new("img_demand", current_user.login, Image.find(i).ms_image_id, parameters)
    end
  end

  def demande_download(ids, operation)
    parameters = { :type_op => operation}
    ms_image_ids = []
    ids.each do |i|
      Statistic.create_stat(current_user.id, i, 3)
      ms_image_ids << Image.find(i).ms_image_id
    end
    api_call('img_demand', current_user.login, ms_image_ids, parameters)
    #Delayed::Job.enqueue ForwardCsRequest.new("img_demand", current_user.login, Image.find(i).ms_image_id, parameters)
  end

  def local_download(ids, operation, location)
    if ids.length > 1
      t = Tempfile.new("#{request.remote_ip}")
      t_zip = t.path+'.zip'
      Zip::File.open(t_zip, Zip::File::CREATE) do |zipfile|
        ids.each do |id|
          extract = Image.find(id.to_i)
          cur_file = extract.send("#{location}_location")
          zipfile.add("#{File.basename(cur_file)}", "public#{cur_file}")
          api_call('lr_stat', current_user.login, extract.ms_image_id, {}) unless Provider.find(extract.provider_id).local?
          Statistic.create_stat(current_user.id, id, OperationLabel.find_by_label(operation).id)
        end
      end
      send_file t_zip, type: 'application/zip', disposition: 'attachment', filename: "#{Server.find_by_is_self(true).name}_download_#{Time.now.strftime("%Y%m%d%H%M%S")}.zip"
      t.close
      t.unlink
    else
      extract = Image.find(ids.first.to_i)
      operation_id = OperationLabel.find_by_label(operation).id
      cur_file = extract.send("#{location}_location")
      send_file "public#{cur_file}", disposition: 'attachment'
      api_call('lr_stat', current_user.login, extract.ms_image_id, {}) unless (Provider.find(extract.provider_id).local? || Server.itself?(PTREF_SERVER_NAME))
      Statistic.create_stat(current_user.id, extract.id, operation_id) if operation_id
      @aff_txt += "Basse définition téléchargée : #{extract.original_filename}\n"
    end
  end

  def remote_access(ids,operation)
    ids.each do |i|
      im = Image.find(i)
      operation_id = OperationLabel.find_by_label(operation).id
      Statistic.create_stat(current_user.id, i, operation_id)
      case operation
      when 'BD'
        api_call('lr_stat', current_user.login, im.ms_image_id, {})
      when 'HD'
        api_call('hr_stat', current_user.login, im.ms_image_id, {})
      end
    end
  end

  def remote_download(ids, operation, location)
    if ids.length > 1
      t = Tempfile.new("#{request.remote_ip}")
      t_zip = t.path+'.zip'
      Zip::File.open(t_zip, Zip::File::CREATE) do |zipfile|
        ids.each do |id|
          im = Image.find(id)
          video_url = im.send("#{location}_location")
          video_filename = File.extname(File.basename(video_url))==".#{im.ms_id}"? File.basename(video_url) : im.original_filename.gsub(File.extname(im.original_filename),".#{im.ms_id}")
          t = Tempfile.new("video_#{id}_")
          t_video = t.path+".#{im.ms_id}"
          open(t_video, 'wb') do |file|
            file << open(video_url).read
          end
          zipfile.add("#{video_filename}", "#{t_video}")
          operation_id = OperationLabel.find_by_label(operation).id
          case operation
          when 'BD'
            api_call("lr_stat", current_user.login, im.ms_image_id, {})
          when 'HD'
            api_call("hr_stat", current_user.login, im.ms_image_id, {})
          end
          Statistic.create_stat(current_user.id, id, operation_id)
        end
      end
      send_file t_zip, type: 'application/zip', disposition: 'attachment', filename: "#{Server.find_by_is_self(true).name}_download_#{Time.now.strftime("%Y%m%d%H%M%S")}.zip"
      t.close
      t.unlink
    else
      i = ids.first
      im = Image.find(i)
      video_url = im.send("#{location}_location")
      video_filename = File.extname(File.basename(video_url))==".#{im.ms_id}"? File.basename(video_url) : im.original_filename.gsub(File.extname(im.original_filename),".#{im.ms_id}")
      t = Tempfile.new("video_#{i}_")
      t_video = t.path+".#{im.ms_id}"
      open(t_video, 'wb') do |file|
        file << open(video_url).read
      end
      send_file t_video, type: "application/#{im.ms_id}", disposition: 'attachment', filename: video_filename
      t.close
      t.unlink
      operation_id = OperationLabel.find_by_label(operation).id
      Statistic.create_stat(current_user.id, i, operation_id)
      case operation
      when 'BD'
        api_call("lr_stat", current_user.login, im.ms_image_id, {})
      when 'HD'
        api_call("hr_stat", current_user.login, im.ms_image_id, {})
      end
    end
  end


  private

  def safe_directory_name_escape(directory_name)
    Iconv.new('US-ASCII//TRANSLIT', 'utf-8').iconv(directory_name).gsub("'", '').gsub(/[^A-z]/, '_')
  end

  def flux_download(dwn_path, *images_ids)
    operation = 'HD'
    images_ids.each do |id|
      extract = Image.find(id.to_i)
      next if extract.nil? || session[:provhd][extract.provider_id] != 1

      if MS.include? extract.ms_id
        requ = marek_request_build(extract.ms_picture_id)
        uri = URI('http://ftp.pixpalace.com/cgi-bin/download_pixpalace.zip')
        res = Net::HTTP.post_form(uri, 'from' => requ)
        tempfile = Tempfile.new('wb')
        tempfile.binmode
        tempfile.write(res.body)
        tempfile.rewind
        pict = "public/flux/#{extract.file_name}"
        File.open(pict, 'wb'){ |f| f.write(tempfile.read) }
        tempfile.close
        tempfile.unlink
        Net::SCP.upload!('192.168.0.12', 'v2',
                         pict, "#{dwn_path}#{extract.file_name}",
                         :ssh => { password: 'qc28ng77'})
      else
        FileUtils::cp( "public#{extract.hires_location}", dwn_path )
      end
      Statistic.create_stat(current_user.id, extract.id, OperationLabel.find_by_label(operation).id)
    end
  end

  def marek_download_request(*images_ids)
    dwn = {}
    images_ids.each do |id|
      extract = Image.find(id.to_i)
      next if extract.nil? || !extract.has_right(current_user,'HD')

      if MS.include? extract.ms_id
        serv = MS[extract.ms_id]
        serv_ms = extract.ms_id
        serv_cgi = "#{serv}/cgi-bin/download_pixpalace.zip"
        requ = marek_request_build(extract.ms_picture_id)
        unless dwn.key? serv_ms
          dwn[serv_ms]  = {}
          dwn[serv_ms]['ids'] = []
          dwn[serv_ms]['urls'] = {}
        end
        dwn[serv_ms]['ids'] << id
        dwn[serv_ms]['urls'][serv_cgi] = [] unless dwn[serv_ms]['urls'].key? serv_cgi
        dwn[serv_ms]['urls'][serv_cgi] << "#{serv}/cgi-bin/download_single.zip?from=#{requ}"

      elsif Server.itself? extract.ms_id
        serv_ms = extract.ms_id
        unless dwn.key? serv_ms
          dwn[serv_ms]  = {}
          dwn[serv_ms]['ids'] = []
          dwn[serv_ms]['urls'] = {}
        end
        unless dwn[serv_ms]['urls'].key? 'LOCAL'
          dwn[serv_ms]['urls']['LOCAL'] = []
          dwn[serv_ms]['urls']['LOCAL'][0] = '/downloads?definition=LHD'
        end
        dwn[serv_ms]['urls']['LOCAL'][0] += "&amp;ids[]=#{id}"
      end
    end
    dwn
  end

  def marek_request_build(ms_pic_id)
    params = []
    params << '9Pu0NkL41'
#    if ms_pic_id.to_s.length > 20
#      params << marek_decrypt(ms_pic_id)
#    else
    params << ms_pic_id
#    end
    params << current_user.title.server.name
    params << request.remote_ip
    params << current_user.title.name
    params << current_user.login
    marek_crypt(params.join('@@@'))
  end

end