# encoding: utf-8
require  File.expand_path('../../../../../lib/pixways', __FILE__)
require  File.expand_path('../../../../../lib/pixways/searches_helper', __FILE__)

class Feed

  include Pixways

  def initialize(current)
    @current = current
  end

  private

  def process

    yield

    if @current.feed == :local
      base_name = I18n.transliterate(File.basename(@current.path).force_encoding('UTF-8')).gsub(/[^a-zA-Z0-9\._]/, '_')
    else
      base_name = File.basename(@current.path)
    end
    #raise PpException::NoReceptionDate if @current.meta[:reception_date].blank?
    reception_date = @current.meta[:reception_date].split(' ')[0]
    @current.meta[:provider_id] = @current.provider.id
    @current.meta[:file_name] = base_name
    @current.meta[:thumb_location] = "/images/photos/#{@current.provider.string_key}/#{reception_date}/thumbs/#{base_name}"
    @current.meta[:medium_location] = "/images/photos/#{@current.provider.string_key}/#{reception_date}/med/#{base_name}"
    @current.meta[:ratio] = @current.meta[:max_avail_width].to_f / @current.meta[:max_avail_height].to_f if @current.meta[:max_avail_width].to_f>0 && @current.meta[:max_avail_height].to_f>0
    copyright = @current.provider.copyright_rule
    @current.meta.each{ |k,v| copyright.gsub!('#{:'+k.to_s+'}',v.to_s)}
    copyright.gsub!(/#\{:(.+)\}/,'')
    if @current.provider.copyright_symbol == true
      copyright = "© #{copyright}" unless copyright[0..0] == '©' || copyright.blank?
    end
    @current.meta[:normalized_credit] = copyright
  end

  def write_files
    if @current.feed == :pixpalace
      if Server.itself? PP2_SERVER_NAME
        write_thumb(160)
        write_med(600)
        keep_or_delete_source(@current.folder)
      else
        write_thumb
        copy_or_move_med(@current.folder)
      end

    elsif @current.feed == :local
      # a solution to avoid overload server as seen on hommell
      #write_thumb
      #write_med
      write_thumb_med
      copy_or_move_high(@current.folder)

    elsif @current.feed == :pixtrakk
      write_thumb
      copy_or_move_med(@current.folder)

    else
      raise  PpException::UnknownFeedType
    end
  end

  def save_on_fs_and_db
    im = ::Image.new(@current.meta)
    check_content(im)
    im.save!
    write_files
  end

  def seek_then_replace
    im_msimageid = ::Image.find_by_ms_image_id(@current.meta[:ms_image_id])
    #im_msimageid = ::Image.where('original_filename=? and  provider_id=? and ms_image_id=?',@current.meta[:original_filename],@current.meta[:provider_id],@current.meta[:ms_image_id]).first
    im_origname_provid = ::Image.where('original_filename=? and  provider_id=? and ms_image_id!=?',@current.meta[:original_filename],@current.meta[:provider_id],@current.meta[:ms_image_id]).first
    if (@current.meta[:update_msid] == 'new') or (@current.meta[:update_msid] == 'update')
      # ms_image_id found
      if !im_msimageid.nil?
        # original_filename / provider_id not found
        if im_origname_provid.nil?
          #LOG.debug("Image #{@current.meta[:file_name]} with ms_image_id #{@current.meta[:ms_image_id]} tagged as '#{@current.meta[:update_msid]}' already exists and is updated")
          @current.meta[:reception_date] = im_msimageid[:reception_date]
          update_photo(im_msimageid)
          # original_filename / provider_id found
        else
          #LOG.debug("Image #{@current.meta[:file_name]} with ms_image_id #{@current.meta[:ms_image_id]} tagged as '#{@current.meta[:update_msid]}' already exists with a different ms_image_id (#{im_origname_provid.ms_image_id}) and is updated.")
          @current.meta[:reception_date] = im_origname_provid[:reception_date]
          update_photo(im_origname_provid)
        end
        # ms_image_id not found
      else
        # original_filename / provider_id not found
        if im_origname_provid.nil?
          #LOG.debug("Image #{@current.meta[:file_name]} with ms_image_id #{@current.meta[:ms_image_id]} tagged as '#{@current.meta[:update_msid]}' does not exist and is created.")
          create_photo
          # original_filename / provider_id found
        else
          #LOG.debug("Image #{@current.meta[:file_name]} with ms_image_id #{@current.meta[:ms_image_id]} tagged as '#{@current.meta[:update_msid]}' already exists with a different ms_image_id (#{im_origname_provid.ms_image_id}). Existing picture is updated.")
          @current.meta[:reception_date] = im_origname_provid[:reception_date]
          update_photo(im_origname_provid)
        end
      end
    else
      # raise PpException::MsImageIdProblem
      #im_old = ::Image.find_by_ms_image_id(@current.meta[:ms_image_id])
      if im_msimageid.nil?
        create_photo
      else
        test_reception_date = @current.meta[:reception_date].to_time(:utc)
        test_reception_date = test_reception_date.change(year: test_reception_date.year+2000) if (test_reception_date.year < 2000)
        if test_reception_date >= im_msimageid[:reception_date].utc
          @current.meta[:reception_date] = im_msimageid[:reception_date]
          update_photo(im_msimageid)
          LOG.debug("#{@current.meta[:file_name]} replaced")
        else
          LOG.warn("Actual picture reception_date #{im_msimageid[:reception_date].utc} is more recent than new picture's one : #{test_reception_date}")
          raise PpException::OlderServerTimeForUpdate
        end
      end
    end
    write_files
  end

  def local_seek_then_replace
    im_old = ::Image.where(:original_filename => @current.meta[:original_filename],:provider_id => @current.meta[:provider_id], :ms_id => @current.meta[:ms_id]).first
    if im_old.nil?
      im = ::Image.new(@current.meta)
      #check_content(im)
      im.save!
    else
      test_reception_date = @current.meta[:reception_date].to_time(:utc)
      if test_reception_date >= im_old[:reception_date].utc
        @current.meta[:reception_date] = im_old[:reception_date]
        im_old.update_attributes(@current.meta)
        check_content(im_old)
        LOG.debug("#{@current.meta[:file_name]} replaced")
      else
        LOG.warn("old picture #{im_old[:reception_date].utc} more recent than new #{@current.meta[:reception_date].to_time(:utc)}")
        raise PpException::OlderServerTimeForUpdate
      end
    end
    write_files
  end

  def check_content(media)
    unless media.reception_date.year > 2000
      media.reception_date = media.reception_date.change(year: media.reception_date.year+2000)
    end

    if media.fonds == 1
      media.medium_location = media.title
      #media.hires_location = media.location
    end

    #Hide pictures in error
    # if media.hires_location.include?("/usr/PPserver/PA_only/")
    #   media.content_error = true
    # end
  end

  def save_reportage(img)
    unless !img.provider.pixtech.blank? && img.provider.pixtech.name=='parismatch' && !(Integer(img.reportage,10).is_a?(Integer) rescue false)
      rep = Reportage.where(string_key: img.provider.string_key, no_reportage: img.reportage, offre: false).first
      if rep.nil?
        date_cr = img.date_created.blank? ? Time.now : img.date_created
        rep = Reportage.create(no_reportage: img.reportage, string_key: img.provider.string_key, prem_photo: img.ms_image_id,
                               rep_titre: img.headline, rep_date: date_cr, signatur: img.normalized_credit, offre: false)
        ReportagePhoto.create(reportage_id: rep.id, photo_ms_id: img.ms_image_id)
        LOG.info "Reportage #{img.reportage} created with image #{img.file_name}"
      else
        unless rep.nb_photos >= MAX_IMG_REPORTAGE || !ReportagePhoto.where(reportage_id: rep.id, photo_ms_id: img.ms_image_id).empty?
          ReportagePhoto.create(reportage_id: rep.id, photo_ms_id: img.ms_image_id)
          LOG.info "Picture #{img.file_name} added to reportage #{img.reportage}"
        end
      end
    end
  end

  def update_reportage(img)
    # Check if picture already in reportage_photos table
    rep_photo = ReportagePhoto.joins(:reportage).where(photo_ms_id: img.ms_image_id,reportages: {offre: false}).first
    # Picture is not in reportage_photos table, add it if reportage not blank
    if rep_photo.nil? && !img.reportage.blank?
      save_reportage(img)
    # Picture already in table but its reportage reference has changed
    elsif !rep_photo.nil? && rep_photo.reportage.no_reportage != img.reportage
      rep_photo.destroy
      save_reportage(img)
    end
  end

  def remove_update_msid
    @current.meta.delete_if {|key, value| key == 'update_msid'.to_sym }
  end

  def create_photo
    remove_update_msid
    im = ::Image.new(@current.meta)
    check_content(im)
    im.save!
    save_reportage(im) unless im.reportage.blank?
  end

  def update_photo(img)
    begin
      remove_update_msid
      img.update_attributes(@current.meta)
      img.update_attributes(content_error: 0)
      img.update_attributes(instructions: nil) if @current.meta[:instructions].blank?
      check_content(img)
      thumb_location_old = PROCESSOR_CONFIG[:paths][:out]+img.thumb_location
      medium_location_old = PROCESSOR_CONFIG[:paths][:out]+img.medium_location
      img.save!
      FileUtils.rm_f(thumb_location_old)
      FileUtils.rm_f(medium_location_old)
      update_reportage(img)
    rescue ActiveRecord::RecordNotUnique => e
      LOG.error"DuplicateEntry : #{e}"
      raise PpException::DuplicateEntry
    rescue => e
      LOG.error"UpdateError : #{e}"
      raise PpException::UpdateError
    end
  end

  def write_thumb(fit_size=320)
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:thumb_location]))
    thumb = @current.media.fit_square(fit_size)
    thumb.write(PROCESSOR_CONFIG[:paths][:out]+@current.meta[:thumb_location]){ self.quality = 80 }
    thumb.destroy!
    add_watermark(@current.meta[:thumb_location],'thumb_location')
  end

  def write_med(fit_size=1200)
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:medium_location]))
    file = Magick::Image.read(@current.path).first
    med = file.resize_to_fit(fit_size,fit_size)
    med.write(PROCESSOR_CONFIG[:paths][:out]+@current.meta[:medium_location]){ self.quality = 80 }
    med.destroy!
    add_watermark(@current.meta[:medium_location],'medium_location')
  end

  def write_thumb_med(fit_size_thumb=600,fit_size_med=1200)
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:thumb_location]))
    thumb = @current.media.fit_square(fit_size_thumb)
    thumb.write(PROCESSOR_CONFIG[:paths][:out]+@current.meta[:thumb_location]){ self.quality = 80 }
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:medium_location]))
    med = @current.media.fit_square(fit_size_med)
    med.write(PROCESSOR_CONFIG[:paths][:out]+@current.meta[:medium_location]){ self.quality = 80 }
    thumb.destroy!
    med.destroy!
    add_watermark(@current.meta[:thumb_location],'thumb_location')
    add_watermark(@current.meta[:medium_location],'medium_location')
  end

  def copy_or_move_med(folder_type)
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:medium_location]))
    if folder_type == :hotfolder
      FileUtils.mv(@current.path, PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:medium_location]))
      add_watermark(@current.meta[:medium_location],'medium_location')
    elsif folder_type == :coldfolder
      FileUtils.cp(@current.path, PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:medium_location]))
      add_watermark(@current.meta[:medium_location],'medium_location')
    else
      raise  PpException::UnknownFolderProcessing
    end
  end

  def keep_or_delete_source(folder_type)
    if folder_type == :hotfolder
      FileUtils.rm(@current.path)
    else
      raise  PpException::UnknownFolderProcessing
    end
  end

  def copy_or_move_high(folder_type)
    FileUtils::makedirs(PROCESSOR_CONFIG[:paths][:out]+File.dirname(@current.meta[:hires_location]))
    if folder_type == :hotfolder
      FileUtils.mv(@current.path, PROCESSOR_CONFIG[:paths][:out]+@current.meta[:hires_location])
    elsif folder_type == :coldfolder
      FileUtils.cp(@current.path, PROCESSOR_CONFIG[:paths][:out]+@current.meta[:hires_location])
    else
      raise PpException::UnknownFolderProcessing
    end
  end

  def add_watermark(location_path,location)
    if File.file?("#{Rails.public_path}#{location_path}") && (Server.type_is?('PIXTECH') || !@current.provider.pixtech_id.blank?)
      pixtech_name = @current.provider.get_pixtech_name
      watermark_locations = @current.provider.pixtech_id.blank? ? [] : PixtechParam.where(name: 'watermark_location', pixtech_id: @current.provider.pixtech_id).pluck(:value)
      watermark_locations.each do |watermark_location|
        if watermark_location == location
          watermark = Pixways.get_pixtech_param_value(pixtech_name,'watermark') unless pixtech_name.blank?
          unless watermark.blank?
            watermark_file = "#{Rails.public_path}#{PICTURES_PATH}#{watermark}"
            if File.file?(watermark_file)
              watermark=Magick::Image.read(watermark_file).first
              file_to_mark = Magick::Image.read("#{Rails.public_path}#{location_path}").first
              case pixtech_name
              when 'saif'
                if @current.meta[:ratio] >= 1
                  watermark.resize_to_fit!(file_to_mark.columns * 0.20)
                else
                  watermark.resize_to_fit!(file_to_mark.rows * 0.20)
                end
                file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::NorthGravity, 0, file_to_mark.rows * 0.05)
                file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::SouthGravity, 0, file_to_mark.rows * 0.05)
                file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::EastGravity, file_to_mark.columns * 0.05, 0)
                file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::WestGravity, file_to_mark.columns * 0.05, 0)
              when 'lightmotiv'
                watermark_ratio = watermark.columns.fdiv(watermark.rows)
                if @current.meta[:ratio] > watermark_ratio
                  watermark.resize_to_fit!(file_to_mark.rows * 0.75 * watermark_ratio)
                else
                  watermark.resize_to_fit!(file_to_mark.columns * 0.75)
                end
                file_to_mark = file_to_mark.dissolve(watermark, 0.5, 1, Magick::CenterGravity)
              when 'christophel'
                # watermark.resize_to_fit!(file_to_mark.columns * 0.5,file_to_mark.rows * 0.1)
                # file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::NorthEastGravity, file_to_mark.columns * 0.1, file_to_mark.rows * 0.05)
                # file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::NorthWestGravity, file_to_mark.columns * 0.15, file_to_mark.rows * 0.33)
                # file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::SouthEastGravity, file_to_mark.columns * 0.15, file_to_mark.rows * 0.33)
                # file_to_mark = file_to_mark.dissolve(watermark, 1, 1, Magick::SouthWestGravity, file_to_mark.columns * 0.1, file_to_mark.rows * 0.05)
                if @current.meta[:ratio] < 1
                  watermark.resize_to_fit!(file_to_mark.columns)
                else
                  watermark.resize_to_fit!(file_to_mark.rows)
                end
                file_to_mark.composite_tiled!(watermark)
              when 'parismatch'
                if @current.meta[:ratio] < 1
                  watermark.resize_to_fit!(file_to_mark.columns * 0.75)
                else
                  watermark.resize_to_fit!(file_to_mark.rows * 0.75)
                end
                file_to_mark.composite_tiled!(watermark)
              end
              watermark.destroy!
              file_to_mark.write("#{Rails.public_path}#{location_path}"){ self.quality = 80 }
              file_to_mark.destroy!
            end
          end
        end
      end
    end
  end

end