#! /usr/bin/env ruby
=begin
= rename.rb -- rename files

= SYNOPSIS
  rename.rb [from] [to] <file>

= DESCRIPTION
rename.rb inputs changes ((|[from]|)) to ((|[to]|)) of ((|<file>|)). 

= OPTIONS
please read output of 
  % rename.rb --help
or
  % rename.rb

==COPYRIGHT 
daktu32@ep.sci.hokudai.ac.jp

== HISTORY
2003-09-?? created by daktu32 , v0.1   released
2003-11-18 modified by daktu32, v0.1.1 released
2003-12-20 modified by daktu32, v0.2   released
=end

# rename.rb version

Rename_VERSION = 0.2

#----------------    def class RenameFilter    ----------------#
class RenameFilter

  def initialize(path, from, to)
    @path = path
    @from = Regexp.new(from)
    @to = to
    @srclist = Hash.new()
    @newlist = Hash.new()
  end

  def make_filelist(path)
    basename = File.basename(path)
    fullpath = File.dirname(File.expand_path(path))
    if basename =~ @from
      unless @srclist[fullpath]
	@srclist[fullpath] = Array.new()
	@newlist[fullpath] = Array.new()
      end
      @srclist[fullpath] << basename
      @newlist[fullpath] << basename.gsub(@from, @to)
    end
  end

  def make_dirlist(dir)

  end

  def sort_list(list)
    sorted_list = list.to_a.sort { |a, b|
      (b[0].length <=> a[0].length)*2 + (a[1] <=> b[1])
    }
    return sorted_list
  end
  


  def prename
    if ($OPT_r) || ($OPT_recursible)
      @path.each do |path|
	if File.exist?(path)
	  make_filelist(path)
	  if File.directory?(path)
	    Dir.glob(path+"**/**").each {|pa|
	      make_filelist(pa) if File.exist?(pa)
	    }
	  end
	end
      end
    else
      @path.each do |path|
	make_filelist(path) if  File.exist?(path)
      end
    end  
    @srclist =  sort_list(@srclist);@newlist = sort_list(@newlist) # what the return value  is when self is sum.
    return @srclist, @newlist
  end
  
=begin

  def prename
    if ($OPT_r) || ($OPT_recursible)
      @path.each do |path|
	Dir.glob(path+"**/**/**/**/**").each {|pa|
	  make_filelist(pa) if File.exist?(pa)
	}
      end
    else
      @path.each do |path|
	make_filelist(path) if  File.exist?(path)
      end
    end  
    @srclist =  sort_list(@srclist);@newlist = sort_list(@newlist) # what the return value  is when self is sum.
    return @srclist, @newlist
  end

=end

  def rename
    @srclist.each_index {|m|
      @srclist[m][1].each_index do |n|
	srcpath = @srclist[m][0] + "/" + @srclist[m][1][n]
	newpath = @srclist[m][0] + "/" + @newlist[m][1][n]
	File.rename(srcpath, newpath)
      end
    }
  end

end

#----------------    end class RenameFilter    ----------------#





  #--------------------   subroutin  -----------------------#

def sure?
  print "\n"
  print "Do you sure rename? (y/n) "
  loop{
    flag = STDIN.gets.chomp
    if flag == "y" then
      return true
    elsif flag == "n" then
      return false
    else
      print "please answer yes or no. (y/n) "
    end
  }
end

def maxvalue(strary)
  max = 0
  strary.each do |a|
    if max < a.length
      max = a.length
    end
  end
  return max
end

=begin

def showlist(src, new)
  src.each_pair {|dir, srcfiles|
    print "\n"+dir+":\n"
    max = maxvalue(srcfiles)    # get the max length of srcfiles string.
    srcfiles.each_index do |n|
      space = max - srcfiles[n].length # get the space
      print "    #{srcfiles[n]+" "*(space)}  =>  #{new[dir][n]}\n"
    end
  }
end

=end

def showlist(src, new)
  src.each_index {|m|
    print "\n"+src[m][0]+":\n"
    max = maxvalue(src[m][1])    # get the max length of srcfiles string.
    src[m][1].each_index do |n|
      space = max - src[m][1][n].length # get the space
      print "    #{src[m][1][n]+" "*(space)}  =>  #{new[m][1][n]}\n"
    end
  }
end

def show_help
  print <<EOF

Name:
  rename2.rb -- rename your files
  
Describe:
  rename2.rb will rename your files.
   
USAGE: 
  rename2.rb ((option)) [from] [to] <file>

OPTIONS:

  -h, --help:  
               show help
  -f, --force: 
               rename without your recommonds
  -n         : 
               will not rename, only show list
  -r, --recursible:  
               recursible jobs. rename under 3 direcrtories.


== COPYRIGHT 
daktu32@ep.sci.hokudai.ac.jp

== HISTORY
2003-09-?? created by daktu32 , v0.1   released
2003-11-18 modified by daktu32, v0.1.1 released
2003-12-20 modified by daktu32, v0.2   released    

EOF
  exit 
end

  #------------------------ test ---------------------------#

def test_rename  
  Dir.mkdir("testdir")
  ofs = open("testdir/Foo.txt", "w")
  ofs.print "this is Foo"
  ofs.close
  begin
    # test
    rf1 = RenameFilter.new(["testdir/Foo.txt"], "Foo", "Bar")
    rf1.prename
    rf1.rename
  ensure
    # rm testdir
    File.delete("testdir/Bar.txt")
    Dir.rmdir("testdir")
  end
  exit
end



if $0 == __FILE__ then   

  #--------------------  parce option  ---------------------#
  require "getopts"
  
  unless getopts("htfvrn", "help", "test", "force", "version", "recursible")
  print "#{$0}:illegal options. please exec this program with \"-h/--help\". \n"
    exit
  end

  # show usage / help
  if ($OPT_h)
    print "usage: '#{$0} from to path'\n"
    exit
  elsif ($OPT_help)
    show_help
    exit
  elsif ($OPT_v) || ($OPT_version)
    print "rename.rb ver.", Rename_VERSION, "\n"
    exit
  end

  test_rename if ($OPT_test) || ($OPT_t)

  #--------------------  main routin  ----------------------#
  raise ArgumentError, "Arugument is not enough. 'usage: #{$0} from to path'" if ARGV.length < 3

  from = ARGV[0]
  to   = ARGV[1]
  path = ARGV.slice(2..ARGV.size-1)

  fn = RenameFilter.new(path, from, to)
  src, new = fn.prename

  if src.size == 0 then
    exit
  else
    showlist(src, new)
    exit if ($OPT_n)
    unless ($OPT_force) || ($OPT_f) 
      if !sure?
	print "Bye.  \n"
	exit
      end
    end
    fn.rename
    print "done.\n"
  end
end
