'use strict'

const logQueue = require('./log-queue')

let questions
let currentQuestion
let answers
let currentOptions
let currentOptionsPointer
let currentQuestionId
let done

class StateMachine {
  constructor (rli, colors) {
    this.rli = rli
    this.colors = colors
  }

  showPrompt () {
    this.rli.write(this.colors.ANSWER)
    this.rli.prompt()
  }

  onKeypress (key) {
    if (!currentOptions || !key) {
      return
    }

    if (key.name === 'tab' || key.name === 'right' || key.name === 'down') {
      this.suggestOption(currentOptionsPointer + 1)
    } else if (key.name === 'left' || key.name === 'up') {
      this.suggestOption(currentOptionsPointer - 1)
    }

    if (!key.ctrl && !key.meta && key.name !== 'enter' && key.name !== 'return') {
      key.name = 'escape'
    }
  }

  suggestOption (index) {
    if (!currentOptions) {
      return
    }

    if (index === -1) {
      currentOptionsPointer = currentOptions.length - 1
    } else if (index === currentOptions.length) {
      currentOptionsPointer = 0
    } else {
      currentOptionsPointer = index
    }

    this.rli._deleteLineLeft()
    this.rli._deleteLineRight()
    this.rli.write(currentOptions[currentOptionsPointer])
  }

  kill () {
    currentOptions = null
    currentQuestionId = null
    this.rli.write('\n' + this.colors.RESET + '\n')
    this.rli.close()
  }

  onLine (line) {
    if (currentQuestionId) {
      this.rli.write(this.colors.RESET)
      line = line.trim().replace(this.colors.ANSWER, '').replace(this.colors.RESET, '')

      if (currentOptions) {
        currentOptionsPointer = currentOptions.indexOf(line)
        if (currentOptionsPointer === -1) {
          return
        }
      }

      if (line === '') {
        line = null
      }

      if (currentQuestion.boolean) {
        line = (line === 'yes' || line === 'true' || line === 'on')
      }

      if (line !== null && currentQuestion.validate) {
        currentQuestion.validate(line)
      }

      if (currentQuestion.multiple) {
        answers[currentQuestionId] = answers[currentQuestionId] || []
        if (line !== null) {
          answers[currentQuestionId].push(line)
          this.showPrompt()

          if (currentOptions) {
            currentOptions.splice(currentOptionsPointer, 1)
            currentOptionsPointer = -1
          }
        } else {
          this.nextQuestion()
        }
      } else {
        answers[currentQuestionId] = line
        this.nextQuestion()
      }
    }
  }

  nextQuestion () {
    currentQuestion = questions.shift()

    while (currentQuestion && currentQuestion.condition && !currentQuestion.condition(answers)) {
      currentQuestion = questions.shift()
    }

    logQueue.printLogQueue()

    if (currentQuestion) {
      currentQuestionId = null

      this.rli.write('\n' + this.colors.question(currentQuestion.question) + '\n')
      this.rli.write(currentQuestion.hint + '\n')
      this.showPrompt()

      currentOptions = currentQuestion.options || null
      currentQuestionId = currentQuestion.id
      this.suggestOption(0)
    } else {
      this.kill()
      done(answers)
    }
  }

  process (_questions, _done) {
    questions = _questions
    answers = {}
    done = _done

    this.nextQuestion()
  }
}

module.exports = StateMachine
