require File.dirname(__FILE__) + '/backs3'

module Backs3
  class Backup
    include Backs3
    include AWS::S3

    def initialize(options = {})
      @options = options
      @options['prefix'] ||= ''
    end

    def first_backup?
      last_backup.nil?
    end

    def full_backup
      @options['force-full'] || first_backup? || Time.now.to_i - last_backup > (@options['full'] || 7).days
    end

    def last_backup
      backup_info['last_backup'].to_i
    end

    def backup_key
      @options['prefix'] + @current_backup
    end

    def last_key
      @options['prefix'] + last_backup.to_s
    end

    def files_to_backup
      @files_to_backup ||= begin
        Dir.glob(File.join(@options['folder'], '**', '**')).select do |file|
          if @options['exclude'].blank? || file !~ /#{@options['exclude']}/
            if full_backup || File.mtime(file).to_i > last_backup
              true
            else
              false
            end
          else
            false
          end
        end
      end
    end

    def backup
      @current_backup = Time.now.to_i.to_s
      @files_to_backup = nil
      @backup_info = nil

      establish_connection

      puts "Backup started at #{Time.now}"
      puts "Last backup happened at #{backup_info['last_backup']}"
      puts "Performing %s" % (full_backup ? "full backup" : "incremental backup")

      files_to_backup.each do |filename|
        puts "Backing up #{filename}"
        file_md5 = md5(filename)
        aws_filename = File.join(backup_key, filename)

        object = S3Object.find(aws_filename, @options['bucket']) rescue nil

        if object.nil? || object.metadata[:md5sum] != file_md5
          S3Object.store(aws_filename, open(filename), @options['bucket'])
          object = S3Object.find(aws_filename, @options['bucket'])
          object.metadata[:md5sum] = file_md5
          object.save
        end
      end

      backup_info['last_backup'] = @current_backup
      backup_info['backups'] ||= []
      backup_info['backups'] << @current_backup
      S3Object.store(@options['prefix'] + 's3backup', YAML.dump(backup_info), @options['bucket'])
      puts "Backup completed, #{files_to_backup.size} files backed up"
    end
  end
end