class PhusionPassenger::Utils::TerminalChoiceMenu

def [](name)

def [](name)
  return @index[name]
end

def clear_screen

def clear_screen
  number_of_lines = render_to_string.split("\n").size
  display("\r")
  (number_of_lines - 1).times do
    display(move_up)
  end
end

def display(str)

def display(str)
  STDOUT.write(str)
  STDOUT.flush
end

def display_choices

def display_choices
  display(render_to_string)
end

def getchar(io)

def getchar(io)
  char = io.getc
  char = char.chr if char.is_a?(Integer)
  return char
end

def hide_cursor

def hide_cursor
  display("\x1b[?25l")
end

def index_choices

def index_choices
  index = {}
  @choices.each do |choice|
    index[choice.name] = choice
  end
  return index
end

def initialize(choices)

def initialize(choices)
  @choices = choices.map { |choice| Choice.create(choice) }
  @pointer = 0
  @index   = index_choices
end

def maybe_utf8(utf8, plain)

def maybe_utf8(utf8, plain)
  if ENV['UTF8_MENUS'] == '0'
    return plain
  else
    return utf8
  end
end

def move_up

def move_up
  return "\x1b[0A"
end

def process_cursor_move

def process_cursor_move
  if getchar(STDIN) == "["
    case getchar(STDIN)
    when "A" # up
      @pointer = [@pointer - 1, 0].max
    when "B" # down
      @pointer = [@pointer + 1, @choices.size - 1].min
    end
  end
end

def process_disable_utf8

def process_disable_utf8
  ENV['UTF8_MENUS'] = '0'
end

def process_input

def process_input
  case getchar(STDIN)
  when "\x1b"
    process_cursor_move
    return false
  when " "
    process_toggle
    return false
  when "!"
    process_disable_utf8
    return false
  when "\r"
    return true
  else
    return false
  end
end

def process_toggle

def process_toggle
  @choices[@pointer].toggle!
end

def query

def query
  if STDIN.tty?
    done = false
    begin
      raw_no_echo_mode
      hide_cursor
      while !done
        display_choices
        done = process_input
        clear_screen if !done
      end
    ensure
      restore_mode
      show_cursor
      puts
    end
  else
    display_choices
    puts
  end
end

def raw_no_echo_mode

def raw_no_echo_mode
  input = STDIN.to_inputstream
  output = STDOUT.to_outputstream
  @console = ConsoleReader.new(input, output)
  @console.set_history_enabled(false)
  @console.set_bell_enabled(true)
  @console.set_pagination_enabled(false)
  @terminal_state = @console.getEchoCharacter
  @console.setEchoCharacter(0)
end

def raw_no_echo_mode

def raw_no_echo_mode
  @terminal_state = `stty -g`
  system("stty raw -echo -icanon isig")
end

def render_checkbox(checked)

def render_checkbox(checked)
  return checked ? maybe_utf8("⬢", "(*)") : maybe_utf8("⬡", "( )")
end

def render_pointer(index)

def render_pointer(index)
  return @pointer == index ? maybe_utf8("‣", ">") : " "
end

def render_to_string

def render_to_string
  str = ""
  @choices.each_with_index do |choice, i|
    pointer = render_pointer(i)
    checkbox = render_checkbox(choice.checked)
    str << " #{pointer} #{checkbox}  #{choice.name}\r\n"
  end
  str.chomp!
  return str
end

def restore_mode

def restore_mode
  @console.setEchoCharacter(@terminal_state)
  @console.get_terminal.restore
end

def restore_mode

def restore_mode
  system("stty #{@terminal_state}")
end

def selected_choices

def selected_choices
  @choices.find_all{ |c| c.checked? }.map{ |c| c.name }
end

def show_cursor

def show_cursor
  display("\x1b[?25h")
end