require 'aws/s3'
require 'tempfile'
require 'net/http'

class S3 < Storage

  def initialize(credentials_file = nil, environment = nil)
    begin
      credentials = YAML::load_file(credentials_file)
      @access_key_id = credentials[environment]['access_key_id']
      @secret_access_key = credentials[environment]['secret_access_key']
      @bucket = credentials[environment]['bucket']
      @permission = credentials[environment]['permission'].nil? ? :public_read : credentials[environment]['permission'].to_sym
      check_credencials
    rescue Exception => exception
      return exception.to_s
    end
  end

  def flush_write(attach_options = nil)
    attach_options.styles.each do |style_name, style_value|
      begin
        temp_file = create_temp_file
        transform(style_value, attach_options.assigned_file.path).write(temp_file.path)
        AWS::S3::S3Object.store(attach_options.short_url(style_name), File.open(temp_file.path, 'rb'), @bucket, :access => @permission)
        #temp_file.unlink
      rescue Exception => exception
        attach_options.add_error(exception.to_s)
      end
    end

    unless attach_options.styles.has_key?(:original)
      begin
        AWS::S3::S3Object.store(attach_options.short_url, File.open(attach_options.assigned_file.path, 'rb'), @bucket, :access => @permission)
      rescue Exception => exception
        attach_options.add_error(exception.to_s)
      end
    end
  end

  def flush_delete(queued_for_delete = nil)
    queued_for_delete.each do |file|
      begin
        AWS::S3::S3Object.delete(reajust_url(file), @bucket)
      rescue AWS::S3::NoSuchBucket => exception
        nil
      rescue Exception => exception
        nil
      end
    end
  end

  def url(attach_options = nil, url = '', style = nil)
    file = reajust_url(url)
    AWS::S3::S3Object.url_for(attach_options.interpolate(url, style), @bucket)
  end

  def base64(attach_options = nil, style = nil)
    url_s3 = URI.parse(attach_options.url(style))

    Net::HTTP.start(url_s3.host, url_s3.port) do |http|
      resp = http.get(url_s3.path)
      resp.body
    end
  end

  def set_queued_for_delete(attach_options = nil, styles = {})
    [styles.keys, :original].flatten.map do |style_name|
      attach_options.url(style_name)
    end.compact
  end

  private
  def reajust_url(url = '')
    url.sub(/^(\/)/, '')
  end

  def create_temp_file
    temp_file = Tempfile.open('mm-attach-it-')
    temp_file.close
    return temp_file
  end

  def check_credencials
    begin
      AWS::S3::Base.establish_connection!(
        :access_key_id     => @access_key_id,
        :secret_access_key => @secret_access_key
      )
    rescue Exception => exception
      return exception.to_s
    end

    begin
      AWS::S3::Bucket.find(@bucket)
    rescue AWS::S3::InvalidAccessKeyId => exception
      return exception.to_s
    rescue AWS::S3::SignatureDoesNotMatch
      return exception.to_s
    rescue AWS::S3::AccessDenied => exception
      return exception.to_s
    rescue AWS::S3::NoSuchBucket => exception
      AWS::S3::Bucket.create(@bucket)
    rescue Exception => exception
      return exception.to_s
    end

    return nil
  end

end