// At this stage, you don’t have to worry about the definitions immediately below this text.
package o1.singletons

// The following example is introduced in Chapter 2.1. It isn’t necessary to
// understand its internal workings. Some of the code that follows is not written
// in a beginner-friendly style.

object parrot:

  private var repertoire = List("Yo-Yo Ma and a bottle of rum", "Polly wants a cracker")

  def learnPhrase(newPhrase: String) =
    this.repertoire = newPhrase :: this.repertoire

  def respond(heardPhrase: String): String =
    def firstWordOfInput =
      cleanse(heardPhrase).takeWhile( _ != ' ' )
    def appearsInInput(wordFromRepertoire: String) =
      wordsInInput.exists( areSimilarEnough(_, wordFromRepertoire) )
    def containsAnyWordFromInput(phraseFromRepertoire: String) =
      toWords(phraseFromRepertoire).exists(appearsInInput)
    lazy val wordsInInput = toWords(heardPhrase)
    val response = this.repertoire.find(containsAnyWordFromInput).getOrElse(firstWordOfInput)
    if response.nonEmpty then response + "!" else ""

  private def cleanse(phrase: String): String =
    phrase.replaceAll(raw"[^\w åäöÅÄÖ]+", "")

  private def toWords(phrase: String): Seq[String] =
    cleanse(phrase).toLowerCase.split(" ").toSeq.filter( _.length > 2 )

  private def areSimilarEnough(word: String, another: String) =
    o1.util.editDistance(word, another, 1) <= 1

end parrot

