require "minitest/autorun"
require "./jekyllserver"

class Test_JekyllRunner  < Minitest::Test

  def setup
    @test_startup_folder = Dir.pwd
  end

  def teardown
    Dir.chdir(@test_startup_folder)
  end

  # check_contents:
    # √ the YAML worked
    # √ the jpegs are still viewable
    # categories are done and uploaded

  def set_up_for_jekyll_testing
    FileUtils.rm_rf("./_target")
    FileUtils.mkdir("./_target")
    FileUtils.mkdir("./_target/articles")
    FileUtils.rm_rf("./test_jekyll_site/articles")
    ipad_folder = '/Users/ron/Dropbox/_source'
    jekyll_folder = './test_jekyll_site'
    return JekyllRunner.new(ipad_folder, jekyll_folder, 
      'localhost', 'programming/test-ftp/_target/articles', 'TEST_')
  end
  
  def test_file_copy
    jr = set_up_for_jekyll_testing
    assert(!File.exist?(
      './test_jekyll_site/articles/a.txt'), 
      "mistakenly found a.txt")
    jr.move_ipad_files
    assert(File.exist?(
      './test_jekyll_site/articles/a.txt'), 
      "can't find a.txt")
  end

  def test_jekyll_run
    jr = set_up_for_jekyll_testing
    jr.move_ipad_files
    jr.run_jekyll
    assert(File.exist?(
      './test_jekyll_site/_site/articles/a.txt'), 
      "can't find jekyllated a.txt")
    assert(File.exist?(
      './test_jekyll_site/_site/articles/subfolder/index.html'),
      "can't find jekyllated subfolder")
  end

  def test_we_know_what_to_ftp
    jr = set_up_for_jekyll_testing
    jr.move_ipad_files
    expected_to_ftp = ["a.txt", "anotherfolder", 
      "anotherfolder/f5.txt", "anotherfolder/index.html", 
      "b.txt", "pic.JPG", "subfolder", "subfolder/index.html", 
      "subfolder/sf1.txt", "subfolder/st2.txt"]
    assert_equal(expected_to_ftp, jr.what_to_ftp)
  end

  def test_what_will_be_ftped
    jr = set_up_for_jekyll_testing
    jr.move_ipad_files
    list_of_allegedly_moved_things = jr.ftp_the_files(simulated = true) 
    assert list_of_allegedly_moved_things.include? "/Users/ron/programming/test-ftp/test_jekyll_site/_site/articles/subfolder/index.html to something/subfolder/index.html"
  end

  def test_end_to_end
    jr = set_up_for_jekyll_testing
    jr.run
    assert(File.exist?('./_target/articles/anotherfolder/f5.txt'), 
      "end to end can't find ftped f5.txt from #{Dir.pwd}")  
  end

  def test_setup_teardown_restores_chdir
    result = (`pwd`).chomp
    assert_equal(@test_startup_folder, result)    
  end
    
  def test_chdir_affects_where_backtick_runs
    Dir.chdir('/Users/ron')
    result = (`pwd`).chomp
    assert_equal('/Users/ron', result)
  end
end

require "net/ftp"
require "./passwords"

class JekyllRunner
  def initialize(ipad_folder, jekyll_folder, host_name, host_folder, prefix)
    @ipad = ipad_folder
    @jekyll_folder = jekyll_folder
    @ftp_host_name = host_name
    @ftp_folder = host_folder
    @id_prefix = prefix
  end

  def ftp_connected_to_target
    host = Object.const_get('Passwords::' + @id_prefix + 'USER')
    pass = Object.const_get('Passwords::' + @id_prefix + 'PASSWORD')
    ftp = Net::FTP.new(@ftp_host_name)
    ftp.login(host, pass)
    ftp.chdir(@ftp_folder)
    ftp
  end

  def move_ipad_files
    FileUtils.cp_r("#{@ipad}/.","#{@jekyll_folder}/articles")
  end

  def ftp_mkdir_safely(ftp, folder_string)
    ftp.mkdir(folder_string) unless ftp_folder_exists?(ftp, folder_string)
  end

  def ftp_folder_exists?(ftp, folder_string)
    split = folder_string.split("/")
    proposed_folder = split.last
    ppl = split[0...-1]
    proposed_prefix = "./" + ppl.join("/")
    ftp.list(proposed_prefix).any? { |name| name.match(proposed_folder) }
  end

  def perform_in_folder(new_dir, &block)
      pwd = Dir.pwd
      Dir.chdir(new_dir)
    begin
      result = block.call
    ensure
      Dir.chdir(pwd)
    end
    return result
  end

  def what_to_ftp
    perform_in_folder(@ipad) do
      Dir.glob('**/*').collect { |f| rename_md_to_html(f) }
    end
  end

  def ftp_the_files(simulated = false)
    perform_in_folder("#{@jekyll_folder}/_site/articles") do 
      ftp_connection = ftp_connected_to_target unless simulated
      result = what_to_ftp().collect do |file|
        ftp_one_file(ftp_connection, file, simulated)
      end
      ftp_connection.close unless simulated
      result
    end
  end

  def ftp_one_file(ftp, file_name, simulated)
    unless simulated
      if File::directory? file_name
        ftp_mkdir_safely(ftp, file_name)
      else
        ftp.putbinaryfile(file_name,file_name)
      end
    end
    pwd = simulated ? "something" : ftp.pwd
    return "#{Dir.pwd}/#{file_name} to #{pwd}/#{file_name}"
  end

  def rename_md_to_html(file_name)
    file_name.gsub(/\.md$/,".html")
  end

  def run_jekyll
    perform_in_folder(@jekyll_folder) {`jekyll build`}
  end

  def run
    move_ipad_files
    run_jekyll
    ftp_the_files
  end
end