#!/usr/bin/env ruby

require 'optparse'
require 'yaml'
require 'rubygems'
require 'everyday-cli-utils'
include EverydayCliUtils
import :format, :option

#noinspection RubyResolve
require 'mvr/plugin'

require 'everyday-plugins'
include EverydayPlugins

Plugins.load_plugins 'mvr'

def help_str
  str = <<eos
{NAME}(bd)
    {mvr}(bdfpu) -- Renames a group of files and/or folders using a regular expression

{SYNOPSIS}(bd)
    {mvr}(bdfpu) [options] <{find}(ulfcy)> <{replace}(ulfcy)> {file ...}(fcy)

{DESCRIPTION}(bd)
    {mvr}(bdfpu) is a Ruby script that allows you to rename a group of files and/or folders using a regular expression.
    The {find}(ulfcy) parameter uses normal regular expression syntax (there might be Ruby-specific things, but I doubt it).
    The {replace}(ulfcy) parameter is plain text, using {\\#}(fgr) to insert capture group {#}(fgr) (so {\\1}(fgr) to insert the first capture group).
    The list of files can be as many items as you want, and you can use typical wildcard expressions.
    Any parameter after {replace}(ulfcy) will be interpreted as a file/folder name that should be included in the list of what to rename.

    Parameters:
    <{find}(ulfcy)>     The regular expression for the renaming
    <{replace}(ulfcy)>  The text to replace what the regular expression matches (use {\\#}(fgr) to insert capture group {#}(fgr) (so {\\1}(fgr) to insert the first capture group))
    {file ...}(fcy)   The list of files and/or folders to rename

    Options:
#{MyOptions.opts.summarize.join}
eos
  str.format_all
end

class MyOptions
  extend OptionUtil

  help_option %w(-h --help), desc: 'print out this help'

  #option :exclude_extension, %w(-e --exclude-extension), desc: 'remove the file extension before doing the rename operation.  the extension will be added back on after renaming.'
  option :override_colors, %w(-v --override-colors), desc: 'override the colors with the ones configured by the colorconfig script'
end

Plugins.get :option, MyOptions
Plugins.get :option_with_param, MyOptions

MyOptions.help_str = help_str

MyOptions.parse!

options = MyOptions.options

Plugins.set_var :options, options

#color_opts = {
#    normal:   {
#        fg: :none,
#        bg: :none,
#    },
#    same:     {
#        fg: :black,
#        bg: :white,
#    },
#    conflict: {
#        fg: :white,
#        bg: :red,
#    },
#}
#
#config_file = File.expand_path('~/mvr-colors.yaml')
#
#if options[:override_colors] && File.exist?(config_file)
#  color_opts = YAML::load_file(config_file)
#end
#
#color_opts.each { |opt| Format.color_profile opt[0], fgcolor: opt[1][:fg], bgcolor: opt[1][:bg] }

Plugins.get :color_override

pattern = ARGV.shift

if pattern == 'help' || pattern == '--help' || pattern == '-h'
  puts help_str
  exit
end
if ARGV.length < 2
  puts "\n{Usage}(bdul): {mvr}(bdfpu) <{find}(ulfcy)> <{replace}(ulfcy)> {file ...}(fcy)\n\n".format_all
  puts "Run {mvr}(bdfpu) {help}(bdfcy) for command information.\n\n".format_all
  exit
end
replacement = ARGV.shift
regex       = /#{pattern}/o
mappings    = Hash.new
encountered = Array.new
duplicated  = Array.new
ARGV.each do |filename|
  file_basename        = File.basename(filename)
  directory            = filename[0, (filename.length - file_basename.length)]
  #file_ext      = File.extname(file_basename)
  #if options[:exclude_extension] && file_ext.length > 0
  #  file_basename2       = file_basename[0...-file_ext.length]
  #  replacement_basename = file_basename2.gsub(regex, replacement)
  #  replacement_name     = "#{directory}#{replacement_basename}#{file_ext}"
  #else
  #  replacement_basename = file_basename.gsub(regex, replacement)
  #  replacement_name     = "#{directory}#{replacement_basename}"
  #end
  basename             = Plugins.get :name_change_before, file_basename
  replacement_basename = Plugins.get :name_change_after, basename.gsub(regex, replacement)
  replacement_name     = "#{directory}#{replacement_basename}"
  mappings[filename]   = replacement_name
  if encountered.include?(replacement_name)
    unless duplicated.include?(replacement_name)
      duplicated << replacement_name
    end
  else
    encountered << replacement_name
  end
end

ARGV.clear

len1 = mappings.keys.max do |a, b|
  a.length <=> b.length
end

len2 = mappings.values.max do |a, b|
  a.length <=> b.length
end

len1 = len1.length
len2 = len2.length

if len1 < 3
  len1 = 3
end

if len2 < 3
  len2 = 3
end

border = "+#{'-' * (len1+2)}+#{'-' * (len2+2)}+"

puts border
puts "| #{'Old'.mycenter(len1)} | #{'New'.mycenter(len2)} |"
puts border

mappings.each do |from, to|
  from2 = from.mycenter(len1)
  to2   = to.mycenter(len2)
  if from == to
    from2 = "{#{from2}}(:same)"
    to2   = "{#{to2}}(:same)"
  elsif duplicated.include?(to)
    from2 = "{#{from2}}(:conflict)"
    to2   = "{#{to2}}(:conflict)"
  else
    from2 = "{#{from2}}(:normal)"
    to2   = "{#{to2}}(:normal)"
  end
  puts "| #{from2} | #{to2} |".format_all
end

puts border

print "\nAre you sure you want to rename these files (yes/no or y/n)? "
response = gets.chomp
if response.downcase == 'yes' || response.downcase == 'y'
  mappings.each do |from, to|
    if from != to
      File.rename(from, to)
    end
  end
end