class AR::Narrator

  extend AR::Input
  attr_accessor :printer

  def initialize printer, narrations=[]
    @printer = printer
    @narrations = narrations 
  end

  def narrate text
     Narration.new(self,text).start
  end

  def reprint_cache!
    system "clear"
    print self.printer.cache
  end

  class Narration
    attr_accessor :narrator
    attr_accessor :text
    attr_accessor :printed
    attr_accessor :remaining
    attr_accessor :rules
    attr_accessor :speed_level

    def initialize narrator, text, last_leftover_since_newline="", speed_level=0.7
      @narrator = narrator
      @narrator.printer.add_to_cache "\n"
      @this_word = ""
      @remaining = text

      @first_word = true
      @printed = ""
      @rules = []
      @speed_level = speed_level
      @since_last_line =  last_leftover_since_newline 
    end

    def process str
      result = "#{str}\n" 
      while true #this makes it so we support ellipses 
        altered = result.gsub(/\.\s\./, "..")
        break if altered == result
        result = altered
      end
      #str
      result
    end

    def start
      if rules.empty?
        p = Proc.new do |chr|
          d = 0.025
          d *= speed_level
          d *= 4 if chr == ","
          d *= 10 if ["?","!","."].include? chr
          d
        end
        rules <<  p 
      end
      next_char
    end

    def delay=d
      @delay=d
    end

    def next_char
      if @remaining.empty? and @this_word.empty?
        AR::Input.clear_buffer 
        return @since_last_line
      else
        check_for_next_word
        char = @this_word[0]
        if char == "\n"
          @since_last_line = "" 
        end
        self.narrator.printer.print_s char
        @printed += char
        @this_word[0] = ""
        sleep calc_delay(char)
        next_char 
        
=begin
        input = AR::Input.clear_buffer 
        unless input.nil? 
          self.narrator.printer.put_s "\r"
          self.narrator.printer.put_s @printed
        end
=end
        #
      end
    end

    def calc_delay chr
      delay = 0.0
      rules.map{|r| delay += r.call chr }
      delay
    end
    def console_width
     40 
    end

    def check_for_next_word 
      if @this_word.empty?
        if @remaining[-1] == "\n" and @remaining.length == 1
          @this_word = "\n"
          @remaining = ""  
          return
        end

        @this_word = @remaining.split(" ").first || ""
        if @since_last_line.length + @this_word.length > console_width
          @this_word = "\n" + @this_word
        else
          @this_word = " " + @this_word unless @first_word
          @first_word = false
          @since_last_line += @this_word
        end
        @remaining[0..(@this_word.length-1)] = ""
      end
      @this_word
    end


    def restart
      @remaining = @printed
      @printed = ""
      start
    end

  end

end#module Narrator

