#!/usr/bin/env ruby
require "slang"
include Slang
require "parsedate"
include ParseDate

$file_color =  SL_BG_LGRAY+SL_BLUE
$dir_color =   SL_BG_LGRAY+SL_GREEN
$size_color =  SL_BG_LGRAY+SL_CYAN
$date_color =  SL_BG_LGRAY+SL_MAGENTA
$tree_color =  SL_BG_LGRAY+SL_RED
# $save = []

class Fm < Tree_Pager
  def get_file_line(f, d, p = nil)
    if FileTest.directory?(f)
      return nil if f == "." or f == ".."
      date = File.mtime(f)
      dir = TRUE
    elsif FileTest.file?(f)
      size = File.size(f)
      date = File.mtime(f)
      dir = FALSE
    end
    l = @lelement.new(p)
    l.set_val('f', f)
    l.set_val('s', size)
    if date
      y, mo, dy , h, mi, sec, z, wd = parsedate(date.to_s)
      l.set_val('d', [y, mo, dy, h, mi])
    else
      l.set_val('d', [])
    end
    l.node = dir
    l.parent_node = "."
    l.depth = d
    l
  end
  
  def build_lines
    darray = []
    Dir.foreach(".") do |f|
      darray.push(f)
    end
    darray.sort.each do |f|
      if f
	l = get_file_line(f, 0)
	if l
	  id = @scrw.add_line(l)
	  if id
	    l.id = id
	    @hlines[id] = l
	    @lines[@lines_num] = l
	    @lines_num += 1
	  end
	end
      end
    end  
    @scrw.init_lines(@lines_num)
  end
  
  def draw_bottom
    r = @rmax
    c = @cmin
    slsmg_gotorc(r, c)
    reverse_color
    bottom = sprintf("---curren directory: %s", Dir.pwd)
#    bottom = sprintf("---curren directory: %s %d %d %d", Dir.pwd,
#		      @scrw.line_num, @current_row, @scrw.num_lines)
    slsmg_write_string(bottom)
    slsmg_erase_eol
    normal_color
  end
  
  
  def mouse_b0(c, r)
    @current_row = r
    coll_uncoll
  end

  def mouse_b1(c, r)
    @current_row = r
    coll_uncoll
  end

  def mouse_b2(c, r)
    @current_row = r
    coll_uncoll
  end

  def special_key_actions    
    key_actions_add([?q]) do
      sl_reset
      exit
    end
        
    # CR
    key_actions_add([0xd]) do
      coll_uncoll
    end
  end

  def insert_elements(num)
    l = @lines[num]
    uncollapsed_list = []
    ln = 1
    now = l

    c_dir = Dir.pwd
    Dir.chdir(l.parent_node + "/" + l.get_val('f'))
    darray = []
    Dir.foreach(".") do |f|
      darray.push(f) if f != "." and f != ".."
    end
    darray.sort.each { |f|
      if f
  	n = get_file_line(f, l.depth + 1, l)
  	if n
  	  id = insert_line(now.id, n, num+ln)
  	  if id
  	    n.parent_node = l.parent_node + "/" + l.get_val('f')
  	    now = n
  	    uncollapsed_list << n
  	    ln += 1
  	  end
  	end
      end
    }
    Dir.chdir(c_dir)
    uncollapsed_list
  end
  
  # override Pager.write_line
  def write_line(l, row)
    set_aformat if @aformat == []
    w = 0
    @aformat.each {|f| # f[0]:format_char  f[1]:width
      case(f[0])
      when '+'
	w = write_tree(l, f[1], row)
      when 'f'
	f1 = (f[1] - w).to_s
	fmt = '%-' + f1 + '.' + f1 + 's'
	str = sprintf(fmt, l.get_val('f'))
	if l.node 
	  slsmg_set_color($dir_color) unless row == @current_row
	  slsmg_write_string( str )
	else
	  slsmg_set_color($file_color) unless row == @current_row
	  slsmg_write_string( str )
	end
      when 's'
	fmt = '%' + f[1].to_s + 'd'
	str = sprintf(fmt, l.get_val('s').to_i)
	slsmg_set_color($size_color)  unless row == @current_row
	slsmg_write_string( str )
      when 'd'
	da = l.get_val('d') 
	# date field missing with non-existent symbolic link
	unless da == []
	  fmt = '%' + f[1].to_s + 's'
	  if f[1] >= 16
	    pd = sprintf("%4d %02d/%02d %02d:%02d",
			 da[0], da[1], da[2], da[3], da[4])
	  elsif f[1] >= 11
	    pd = sprintf("%02d/%02d %02d:%02d", 
			 da[1], da[2], da[3], da[4])
	  else
	    pd = sprintf("%02d:%02d", da[3], da[4])
	  end
	  str = sprintf(fmt, pd)
	  slsmg_set_color($date_color) unless row == @current_row
	  slsmg_write_string( str )
	end
      end
      normal_color unless row == @current_row
      slsmg_erase_eol
    }
  end
end

class File_element < Tree_element
  def initialize(p=nil)
    @parent_node = ""
    super(p)
  end
  attr("parent_node", TRUE)
end

mouse_on
exit unless init_terminal(1, 1)

slkp_define_keysym("\040", PAGER_NPAGE) # space
slkp_define_keysym("b", PAGER_PPAGE)
slkp_define_keysym("\033>", PAGER_EOB)
slkp_define_keysym("\033<", PAGER_BOB)

slkp_define_keysym("\033[M\040", SL_MOUSE_B0)
slkp_define_keysym("\033[M\041", SL_MOUSE_B1)
slkp_define_keysym("\033[M\042", SL_MOUSE_B2)

p = Fm.new(0, sltt_screen_rows-1, 0, sltt_screen_cols-1, File_element)
p.set_format('10+ 30f 10s 17d')
p.set_dia

p.main_loop
