#!/usr/bin/env ruby

require 'paint'
require 'open3'


lib = File.expand_path('../../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

SHELL = ENV['SHELL']

require 'shellplay/session'

@session = Shellplay::Session.new
@session.import(ARGV[0])

continue = true
@lastelapsed = 0
@playprompt = true
@sleeptime = (1.0/48.0)

counter = 1
def usage
  puts "\nCommands: "
  puts "  h,?        show help"
  puts "  s          list screens"
  puts "  s#         jump to screen #"
  puts "  <enter>    jump to next screen"
  puts "  p          jump to previous screen"
  puts "  <command>  execute a subcommand in a `$SHELL -c`"
  puts "  x,q        quit"
  puts
end

# generic display method
# 
def display(screen)
  if screen.clearscreen
    if ENV['TERM_PROGRAM'] == 'iTerm.app'
      print "\e]50;ClearScrollback\a"
    else
      print "\033c"
    end
  end
  if screen.displaycommand
    if screen.customprompt
      print screen.customprompt
    else
      print @session.config.prompt
    end
    sleep @sleeptime
    print screen.stdin
    STDIN.gets
    @lastelapsed = screen.timespent
  else
    @lastelapsed = 0
  end
  print screen.stdout
  @playprompt = screen.playprompt
  if screen.stderr != ""
    printf "\n#{Paint[screen.stderr, :red]}"
  end
end

# move to the next screen
def shownext
  if @session.current_screen and @session.current_screen.stdin
    display @session.current_screen
    @session.next
  else
    print Paint["... ", :cyan]
    @playprompt = false
    @lastelapsed = 0
  end
end

# move to the previous screen
def showprevious
  if @session.pointer > 0
    @session.previous
    @session.previous
    display @session.current_screen
    @session.next
  else
    puts "There is no previous screen."
  end
end

# jump to an arbitrary screen
def show(index)
  if @session.show(index) && @session.show(index).stdin
    display @session.show(index)
    @session.next
  else
    puts "You are at the end of the session."
    @lastelapsed = 0
  end
end

print "\n\e[33m>\e[0m Type <enter> to begin."

# main loop
while continue do
  command = STDIN.gets.strip
  case command
  when /^(?:q|x)$/
    puts "\nPlay ended.\n"
    continue = false
    exit
  when /^(?:\?|h)$/
    usage
  when /^p$/
    showprevious
  when /^s$/
    @session.sequence.map { |c| c.stdin }.each_with_index do |l, i|
      printf("   s%-3s %s\n", i, l)
    end
  when /s([0-9]+)/
    show($1)
  when ''
    shownext
  else
    begin
      Open3.popen3(SHELL, "-c", command.strip) do |i, o, e, t|
        o.read.split("\n").each do |line|
          puts line
          sleep @sleeptime
        end
        e.read.split("\n").each do |line|
          puts Paint[line, :red, :bold]
        end
      end
    rescue Exception => e
      puts Paint[e.message, :red, :bold]
    end
  end
  if @playprompt
    print "\n\e[33m>\e[0m "
    printf("\e[33melapsed: \e[0m\e[1;93m#{@session.config.timeformat}s\e[0m ", @lastelapsed) unless @lastelapsed == 0
  end
end
