require 'net/ssh'
require 'pathname'
require 'json'
require 'base64'
namespace :exec_commands do
  desc "Change Server Backup Setting Script"
  task :change_backup_setting,[:site_server_id] => :environment do |task,args|
    if args.site_server_id.present?
      site_server = SiteServer.find(args.site_server_id)
    else
      raise StandardError.new('Please Specify Server ID!')
    end
    thread_key = "change_backup_setting_#{site_server.id}"
    @thread = Multithread.where(:key=>thread_key).first
    begin
      if @thread.nil?
        @thread = Multithread.create(:key=>thread_key,:status=>{"infos"=>[],"status"=>"execing"})
      else
        @thread.update(:status=>{"infos"=>[],"status"=>"execing"})
      end
      ip = site_server.ip
      server_port = site_server.port
      user = site_server.account
      password = site_server.password
      @password = password
      begin 
        Net::SSH.start(ip , user , { password: password, port: server_port}) do |ssh|
        end
      rescue Net::SSH::HostKeyMismatch
        system("ssh-keygen -f \"$HOME/.ssh/known_hosts\" -R #{ip}")
      rescue Errno::ENOTTY
        system("ssh-add \"$HOME/.ssh/id_rsa\"")
      end
      Net::SSH.start(ip , user , { password: password, port: server_port}) do |ssh|
        @no_stdout = true
        crontab_lines_str = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' crontab -l", false, true)
        if site_server.site_server_file_backups.count != 0
          SiteServerFileBackup.init_class_variables(site_server)
          rsnapshot_conf_default = SiteServerFileBackup::DefaultConf
          rsnapshot_conf_exist = check_file_exist_for_ssh(ssh, rsnapshot_conf_default)
          update_thread_infos_for_exec("Checking file backups config...")
          if rsnapshot_conf_exist
            rsnapshot_conf_contents = read_file_for_ssh(ssh, rsnapshot_conf_default)
          else
            rsnapshot_sample_conf = File.expand_path("../../../rsnapshot_sample.conf", __FILE__)
            rsnapshot_conf_contents = File.read(rsnapshot_sample_conf)
            write_file_for_ssh(ssh, rsnapshot_conf_default, rsnapshot_conf_contents)
          end 
          site_server.site_server_file_backups.each do |file_backup|
            rsnapshot_conf_path = file_backup.rsnapshot_conf_path
            if check_file_exist_for_ssh(ssh, rsnapshot_conf_path)
              tmp = read_file_for_ssh(ssh, rsnapshot_conf_path)
            else
              tmp = rsnapshot_conf_contents.clone
            end
            tmp = file_backup.gsub_rsnapshot_conf(tmp)
            write_file_for_ssh(ssh, rsnapshot_conf_path, tmp)
            mkdir_for_ssh(ssh, file_backup.path)
          end
          update_thread_infos_for_exec("Finish writing file backups config!")
        end
        site_server.site_server_db_backups do |db_backup|
          mkdir_for_ssh(ssh, db_backup.path)
        end
        crontab_lines_str = SiteServerFileBackup.write_crontab_setting(site_server, crontab_lines_str)
        crontab_lines_str = SiteServerDbBackup.write_crontab_setting(site_server, crontab_lines_str)
        write_crontab_for_ssh(ssh, crontab_lines_str)
        update_thread_infos_for_exec("Finish setting backups!")
      end
      site_server.site_server_file_backups.update_all(:need_rewrite=>false)
      site_server.site_server_db_backups.update_all(:need_rewrite=>false)
      site_server.update(:need_rewrite_backup_setting=>false)
      @thread.update(:status=>@thread.status.merge({"status"=>"finish"}))
    rescue => e
      @thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.message),"status"=>"error"})
      @thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.backtrace.join("\n")),"status"=>"error"})
    end
  end
  def mkdir_for_ssh(ssh, dir)
    exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' sh -c \"mkdir -p #{dir}\"", false)
  end
  def write_crontab_for_ssh(ssh, crontab_lines_str)
    exec_ssh_command_by_sudo_and_see_output(ssh,"x='#{crontab_lines_str.gsub("\n", '\n').gsub("'","'\"'\"'")}'; sudo -p 'sudo password:' sh -c \"echo '$x'| crontab -\"", false)
  end
  def read_file_for_ssh(ssh, file_name)
    exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' sh -c \"cat #{file_name}\"", false, true)
  end
  def write_file_for_ssh(ssh, file_name, contents)
    exec_ssh_command_by_sudo_and_see_output(ssh,"x='#{contents.gsub("\n", '\n').gsub("'","'\"'\"'")}';sudo -p 'sudo password:' sh -c \"echo '$x' > #{file_name}\"", false)
  end
  def copy_file_for_ssh(ssh, src, dst)
    exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' bash -l -c 'cp #{src} #{dst}'", 1)
  end
  def check_file_exist_for_ssh(ssh, file_name)
    exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' bash -l -c 'if [ -e #{file_name} ]; then echo 1; else echo 0; fi'", false, true).include?('1')
  end
end