#!/usr/bin/env ruby
# encoding: UTF-8

require 'image_optim'
require 'progress'
require 'optparse'

options = {}

option_parser = OptionParser.new do |op|
  op.banner = <<-TEXT
#{op.program_name}, version #{ImageOptim.version}

Usege:
  #{op.program_name} [options] image_path …

  TEXT

  op.on('--[no-]threads NUMBER', Integer, 'Number of threads or disable (defaults to number of processors)') do |threads|
    options[:threads] = threads
  end

  op.on('--[no-]nice NUMBER', Integer, 'Nice levle (defaults to 10)') do |nice|
    options[:nice] = nice
  end

  ImageOptim::Worker.klasses.each do |klass|
    bin = klass.underscored_name.to_sym
    op.on("--[no-]#{bin} PATH", "#{bin} path or disable") do |path|
      options[bin] = path
    end
  end

  op.on_tail('-h', '--help', 'Show full help') do
    puts option_parser.help
    exit
  end

  op.on_tail('-v', '--version', 'Show version') do
    puts ImageOptim.version
    exit
  end
end

begin
  option_parser.parse!
rescue OptionParser::ParseError => e
  abort "#{e.to_s}\n\n#{option_parser.help}"
end

if ARGV.empty?
  abort "specify image paths to optimize\n\n#{option_parser.help}"
else
  io = ImageOptim.new(options)
  paths = ARGV.reject do |arg|
    unless File.file?(arg)
      $stderr << "WARN: #{arg} is not a file\n"
    end
  end
  paths = paths.with_progress('optimizing') if paths.length > 1

  module Space
    SIZE_SYMBOLS = %w[B K M G T P E Z Y].freeze
    PRECISION = 1
    LENGTH = 4 + PRECISION + 1
    COEF = 1 / Math.log(10)

    EMPTY_SPACE = ' ' * LENGTH
    NOT_COUNTED_SPACE = '!' * LENGTH

    class << self
      attr_writer :base10
      def denominator
        @denominator ||= @base10 ? 1000.0 : 1024.0
      end

      def space(size, options = {})
        case size
        when false
          NOT_COUNTED_SPACE.bold.red
        when 0, nil
          EMPTY_SPACE
        else
          number, degree = size, 0
          while number.abs >= 1000 && degree < SIZE_SYMBOLS.length - 1
            number /= denominator
            degree += 1
          end

          "#{degree == 0 ? number.to_s : "%.#{PRECISION}f" % number}#{SIZE_SYMBOLS[degree]}".rjust(LENGTH)
        end
      end
    end
  end

  def size_percent(src_size, dst_size)
    '%5.2f%% %s' % [100 - 100.0 * dst_size / src_size, Space.space(src_size - dst_size)]
  end

  results = io.optimize_images(paths) do |src, dst|
    if dst
      src_size, dst_size = src.size, dst.size
      percent = size_percent(src_size, dst_size)
      dst.replace(src)
      ["#{percent}  #{src}", src_size, dst_size]
    else
      ["------ #{Space::EMPTY_SPACE}  #{src}", src.size, src.size]
    end
  end
  lines, src_sizes, dst_sizes = results.transpose
  $stdout.puts lines, "Total: #{size_percent(src_sizes.inject(:+), dst_sizes.inject(:+))}\n"
end