require 'facets/more/minitar'
require 'zlib'

# Extentions to FileUtils adding compression methods.
#
#--
# TODO Most of this shells out. It would be best to internalize.
#++

module FileUtils

  COMPRESS_FORMAT = {
    'tar.gz'  => 'tar_gzip',
    'tgz'     => 'tar_gzip',
    'tar.bz2' => 'tar_bzip',
    'zip'     => 'zip',

    '.tar.gz'  => 'tar_gzip',
    '.tgz'     => 'tar_gzip',
    '.tar.bz2' => 'tar_bzip',
    '.zip'     => 'zip'
  }

  module_function

  # Compress based on given extension.
  # Supported extensions are:
  # * tar.gz
  # * tgz
  # * tar.bz2
  # * zip

  def compress( format_extension, folder, to_file=nil )
    format = COMPRESS_FORMAT[format_extension]
    if format
      send(format, folder, to_file)
    else
      raise ArgumentError, "unknown compression format -- #{format_extension}"
    end
  end

  # Tar Gzip

  def tar_gzip( folder, to_file=nil )
    require 'zlib'
    to_file ||= File.basename(File.expand_path(folder)) + '.tar.gz'
    puts "tar --gzip -czf #{to_file} #{folder}" if $VERBOSE

    gzIO = Zlib::GzipWriter.new(File.open(to_file, 'wb'))
    Archive::Tar::Minitar.pack(folder, gzIO)

    return File.expand_path(to_file)
  end
  alias_method :tar_gz, :tar_gzip

  # Untar Gzip

  def untar_gzip( file )
    require 'zlib'
    # TODO Write internalized untar_gzip function.

  end
  alias_method :untar_gz, :untar_gzip

  # Tar Bzip2

  def tar_bzip( folder, to_file=nil )
    to_file ||= File.basename(File.expand_path(folder)) + '.tar.bz2'
    cmd = "tar --bzip2 -cf #{to_file} #{folder}"
    puts cmd
    system cmd
    return File.expand_path(to_file)
  end
  alias_method :tar_bz2, :tar_bzip

  # Untar Bzip2

  def untar_bzip( file )
    cmd = "tar --bzip2 -xf #{file}"
    puts cmd
    system cmd
  end
  alias_method :untar_bz2, :untar_bzip

  # Zip

  def zip( folder, to_file=nil )
    to_file ||= File.basename(File.expand_path(folder)) + 'tar.bz2'
    cmd = "zip -cf #{to_file} #{folder}"
    puts cmd
    system cmd
    return File.expand_path(to_file)
  end

  # Unzip

  def unzip( file )
    cmd = "zip -xf #{file}"
    puts cmd
    system cmd
  end

  #

  module DryRun

    module_function

    def compress( format, folder, to_file=nil )
      send(FORMAT_TO_COMPRESS[format], folder, to_file)
    end

    # Tar Gzip

    def tar_gzip( folder, to_file=nil )
      to_file ||= File.basename(File.expand_path(folder)) + '.tar.gz'
      puts "tar --gzip -czf #{to_file} #{folder}"
    end

    # Untar Gzip

    def untar_gzip( file )
      puts "tar --gzip -xzf #{file}"
    end

    # Tar Bzip2

    def tar_bzip( folder, to_file=nil )
      puts "tar --bzip2 -cf #{to_file} #{folder}"
    end
    alias_method :tar_bz2, :tar_bzip

    # Untar Bzip2

    def untar_bzip( file )
      puts "tar --bzip2 -xf #{file}"
    end
    alias_method :untar_bz2, :untar_bzip

    # Zip

    def zip( folder, to_file=nil )
      puts "zip -cf #{to_file} #{folder}"
    end

    # Unzip

    def unzip( file )
      puts "zip -xf #{file}"
    end

  end

end
