# This code is released into the public domain.
#
# author: Koen Van der Auwera koen@atog.be

Shoes.app :width => 600, :height => 305, :scroll => false, :title => "Type It" do
  
  @buffer = ''
  @words = %w{ dit is een woord boe ba doe di li dee moeilijk valt nog al mee ja woopsie daisy }
  @nr_para = @nr_corr = @timer = @nr_missed = 0
  @where = []
  @ypos = [25, 50, 75, 100, 125, 150, 175]
  @typing_color = white
  
  (0..6).each do |i|
    instance_variable_set("@pb#{i}", para('', :left => -20))
  end
    
  keypress do |key|
    case key
    when "\n"
      check_it
    when String
      @buffer += key
    when :backspace
      @buffer.slice!(-1)
    when :tab
      stop_all
      display_score
    end    
    @in.replace @buffer
  end
  
  @area = flow :left => 0, :top => 260, :width => 600 do
    background black, :height => 45
    stack :width => 500 do
      @in = para "Start typing as fast as you can!", :margin => 10, :stroke => @typing_color
    end
    flow :width => 100 do
      @score = para "#{@nr_corr}", :stroke => @typing_color, :size => 25
      para " / ", :stroke => @typing_color
      @time = para "#{@timer}", :stroke => @typing_color
    end
  end
  
  @anim_timer = animate(1) do
    @timer += 1
    @time.replace "#{@timer}"
  end
  
  def put_word_on_screen
    @where << 0
    get_word(@nr_para)
    instance_variable_set("@anim#{@nr_para}", create_animation(@nr_para))
    @nr_para += 1
  end
  
  def check_it
    (0..(@nr_para-1)).each do |i|
      if instance_variable_get("@pb#{i}_buffer") == @buffer
        get_word(i)
        reset(i)
        @nr_corr += 1
        @score.replace @nr_corr
        put_word_on_screen if !@ypos.empty? && @nr_corr % 10 == 0
      end
    end
  end
  
  def create_animation(index, speed=10)
    ypos = @ypos.delete_at(rand(@ypos.size))
    a = animate(speed) do
      unless @where.empty?
        @where[index]+=5
        if @where[index] > 600
          get_word(index)
          @where[index] = 0
          @nr_missed += 1
        elsif @where[index] > 420
          alert_color = red
        elsif @where[index] > 260
          alert_color = orange
        else
          alert_color = green
        end
        instance_variable_get("@pb#{index}").replace(instance_variable_get("@pb#{index}_buffer"), :stroke => alert_color)
        instance_variable_get("@pb#{index}").move(@where[index], ypos)
      end
    end  
  end
  
  def reset(index)
    @where[index] = 0
    @buffer = ''
  end
  
  def get_word(index)
    word = @words[rand(@words.size)]
    instance_variable_set("@pb#{index}_buffer", word)
    instance_variable_get("@pb#{index}").replace(word)
  end
  
  def stop_all
    @anim_timer.stop
    @where.each_with_index do |i, index|
      instance_variable_get("@anim#{index}").stop
    end
  end
  
  def display_score
    stack :left => 0, :top => 0, :width => 600 do
      background red, :height => 305
      stack :left => 25, :top => 120 do
        para "You typed #{@nr_corr} words in #{@timer} sec.", :size => 30
        para "and missed #{@nr_missed} words."
      end
    end
    @area.hide
  end
  
  # first word
  put_word_on_screen
    
end