require 'phi'; include Phi
require 'dialogs'
require 'ini'
require 'indy'

form = Component._load open('form.afm', 'rb').read
load 'control_tree.rb'

def form.save_ftp_host_info(datatext, header)
  serverIni = IniFile.new(File.join(File.dirname($0), 'FtpHost.ini'))
  serverIni['Server', header] = datatext
  serverIni.update
end;

def form.get_host_info(header)
  serverIni = IniFile.new(File.join(File.dirname($0), 'FtpHost.ini'))
  serverName = serverIni['Server', header, header]
  serverName
end

def form.set_function_buttons(value)
  command_panel.controls.each{|i|
    next if i.name == 'abort_button'
    i.enabled = value
  }
  popup_menu1.items.each{|i| i.enabled = value }
  
  ch_dir_button.enabled = value
  create_dir_button.enabled = value
end

def form.change_dir(dirname)
  begin
    set_function_buttons(false)
    id_ftp1.change_dir(dirname)
    id_ftp1.transfer_type = FT_ASCII
    
    current_dir_edit.text = id_ftp1.retrieve_current_dir
    
    # panel3.caption = 'Current directory is: ' + id_ftp1.retrieve_current_dir + '  Remote system is ' + id_ftp1.system_desc
    directory_list_box.items.clear
    id_ftp1.list(directory_list_box.items)
  ensure
    set_function_buttons(true)
  end
end

def form.get_name_from_dir_line(line)
  is_directory = line[0,1] == 'd'
  dosListing = false
  for i in 0..7
    if i == 2 && ! is_directory then
      is_directory = /^<DIR> / =~ line
      if not is_directory then
        dosListing = ['0'..'9'].include? line[0,1]
      else
        dosListing = true
      end
    end
    line.sub!(/^.*? +/, '')
    break if dosListing && i == 2
  end
  return line, is_directory
end

def form.init

  abort_transfer = nil
  transferrign_data = nil
  bytes_to_transfer = nil
  s_time = nil

  average_speed = 0.0

connect_button.on_click = proc do |sender|
  connect_button.enabled = false
  if id_ftp1.connected then
    begin
      if transferrign_data then id_ftp1.abort end
      id_ftp1.quit
    ensure
      # panel3.caption = 'Current directory is: '
      current_dir_edit.text = '/'
      directory_list_box.items.clear
      set_function_buttons(false)
      connect_button.caption = 'Connect'
      connect_button.enabled = true
      connect_button.default = true
    end
  else
    begin
      id_ftp1.user = user_id_edit.text
      id_ftp1.password = password_edit.text
      id_ftp1.host = ftp_server_edit.text
      id_ftp1.connect
      self.change_dir(current_dir_edit.text)
      set_function_buttons(true)
      save_ftp_host_info(ftp_server_edit.text, 'FTPHOST')
    ensure
      connect_button.enabled = true
      if id_ftp1.connected then
        connect_button.caption = 'Disconnect'
        connect_button.default = false;
      end
    end
  end
end

id_log_debug1.on_log_item = proc do |sender, text|
  debug_list_box.item_index = debug_list_box.items.add(text)
  text
end

upload_button.on_click = proc do |sender|
  if id_ftp1.connected then
    if upload_open_dialog1.execute then
      begin
        set_function_buttons(false)
        id_ftp1.transfer_type = FT_BINARY
        
        id_ftp1.put(upload_open_dialog1.file_name, File.basename(upload_open_dialog1.file_name))
        change_dir(id_ftp1.retrieve_current_dir)
      ensure
        set_function_buttons(true)
      end
    end
  end
end

directory_list_box.on_dbl_click = proc do |sender|
  break if ! id_ftp1.connected
  line = directory_list_box.items[directory_list_box.item_index]
  name, is_directory = get_name_from_dir_line(line)
  if is_directory then
    # Change directory
    set_function_buttons(false)
    change_dir(name)
    set_function_buttons(true)
  else
    begin
      save_dialog1.file_name = name
      if save_dialog1.execute then
        set_function_buttons(false)
        id_ftp1.transfer_type = FT_BINARY
        @bytes_to_transfer = id_ftp1.size(name)
        id_ftp1.get(name, save_dialog1.file_name, true)
      end
    ensure
      set_function_buttons(true)
    end
  end
end

delete_button.on_click = proc do |sender|
  break if ! id_ftp1.connected
  line = directory_list_box.items[directory_list_box.item_index]
  name, is_directory = get_name_from_dir_line(line)
  if is_directory then
    begin
      set_function_buttons(false)
      id_ftp1.remove_dir(name)
      change_dir(id_ftp1.retrieve_current_dir)
    ensure
      #
    end
  else
    begin
      set_function_buttons(false);
      id_ftp1.delete(name)
      change_dir(id_ftp1.retrieve_current_dir)
    ensure
      #
    end
  end
end

id_ftp1.on_disconnected = proc do |sender|
  status_bar1.panels[1].text = 'Disconnected.'
end

abort_button.on_click = proc do |sender|
  abort_transfer = true
end

back_button.on_click = proc do |sender|
  break if ! id_ftp1.connected
  begin
    change_dir('..')
  ensure
    #
  end
end

id_ftp1.on_status = proc do |sender, status, status_text|
  debug_list_box.item_index = debug_list_box.items.add(status_text)
  status_bar1.panels[1].text = status_text
end

trace_check_box.on_click = proc do |sender|
  id_log_debug1.active = trace_check_box.checked
  debug_list_box.visible = trace_check_box.checked
  if debug_list_box.visible then
    splitter1.top = debug_list_box.top + 5
  end
end

begin
  set_function_buttons(false)
  id_log_debug1.active = true
  
  ftp_server_edit.text = get_host_info('FTPHOST')
  
  progress_bar1.parent = status_bar1
  progress_bar1.top = 2
  progress_bar1.left = 1
  progress_bar1.width = 142
end

directory_list_box.on_click = proc do |sender|
  break if ! id_ftp1.connected
  line = directory_list_box.items[directory_list_box.item_index]
  name, is_directory = get_name_from_dir_line(line)
  if is_directory then
    download_button.caption = 'Change dir'
  else
    download_button.caption = 'Download'
  end
end

id_ftp1.on_work = proc do |sender, work_mode, work_count|
  totalTime = DateTime.now - s_time
  h,m,sec,ms = totalTime.to_a[3,4]
  sec += m * 60 + h * 3600
  dlTime = sec + ms / 1000.0
  if dlTime > 0 then
    average_speed = (work_count / 1024.0) / dlTime
  end
  s = format('%3.2f KB/s', average_speed)
  case work_mode
  when WM_READ
    status_bar1.panels[1].text = 'Download speed ' + S
  when WM_WRITE
    status_bar1.panels[1].text = 'Uploade speed ' + S
  end;

  if abort_transfer then id_ftp1.abort end

  progress_bar1.position = work_count
  abort_transfer = false
end

id_ftp1.on_work_begin = proc do |sender, work_mode, work_count_max|
  transferrign_data = true
  abort_button.visible = true
  abort_transfer = false
  s_time = DateTime.now
  if work_count_max > 0 then
    progress_bar1.max = work_count_max
  else
    progress_bar1.max = bytes_to_transfer
  end
  average_speed = 0.0
end

id_ftp1.on_work_end = proc do |sender, work_mode|
  abort_button.visible = false
  status_bar1.panels[1].text = 'Transfer complete.'
  bytes_to_transfer = 0
  transferrign_data = false
  progress_bar1.position = 0
  average_speed = 0.0
end

use_passive.on_click = proc do |sender|
  id_ftp1.passive = use_passive.checked
end

ch_dir_button.on_click = proc do |sender|
  set_function_buttons(false)
  change_dir(current_dir_edit.text)
  set_function_buttons(true)
end;

create_dir_button.on_click = proc do |sender|
  s = Phi.input_box('Make new directory', 'Name', '')
  if ! s.empty? then
    begin
      set_function_buttons(false)
      id_ftp1.make_dir(s)
      change_dir(current_dir_edit.text)
    ensure
      set_function_buttons(true)
    end
  end
end

end

form.control_attr_flatten
form.init
form.show
mainloop
