class LucidOperation
  module Gherkin
    FIRST_EXCEPTION = "First must be the first one that is used and can only used once!"
    FINALLY_EXCEPTION = "Finally, except for Ensure and Failed, must be the last one to be used and can only be used once!"

    NEWLINE = /\r?\n/
    OPERATION = /^\s*Operation: (.*)$/
    PROCEDURE = /^\s*Procedure: (.*)$/
    STAR = /^\s*\* (.*)$/
    GIVEN = /^\s*Given (.*)$/
    WHEN = /^\s*When (.*)$/
    THEN = /^\s*Then (.*)$/
    AND = /^\s*And (.*)$/
    FIRST = /^\s*First (.*)$/
    ENSURE = /^\s*Ensure (.*)$/
    FINALLY = /^\s*Finally (.*)$/
    IW_FAILING = /^\s*(?:When|If) failing (.*)$/
    IF_ITT_FAILED = /^\s*If (?:that|this|it) failed (.*)$/
    FAILED = /^\s*Failed (.*)$/
    COMMENT = /^\s*# (.*)$/
    WHITE_SPACE = /^\s*$/

    def self.parse(gherkin_text)
      operation = { operation: '', procedure: '', steps: [], failure: [], ensure: [] }
      has_finally = false
      lines = gherkin_text.split(NEWLINE)

      lines.each do |line|
        case line
        when STAR, GIVEN, WHEN, THEN, AND
          Isomorfeus.raise_error(message: FINALLY_EXCEPTION) if has_finally
          operation[:steps] << $1.strip
        when ENSURE
          operation[:ensure] << $1.strip
        when IW_FAILING, IF_ITT_FAILED, FAILED
          operation[:failure] << $1.strip
        when FIRST
          Isomorfeus.raise_error(message: FIRST_EXCEPTION) if operation[:steps].size > 0
          operation[:steps] << $1.strip
        when FINALLY
          Isomorfeus.raise_error(message: FINALLY_EXCEPTION) if has_finally
          operation[:steps] << $1.strip
          has_finally = true
        when PROCEDURE
          Isomorfeus.raise_error(message: 'No Operation defined!') if operation[:operation].empty?
          Isomorfeus.raise_error(message: 'Procedure already defined!') unless operation[:procedure].empty?
          operation[:procedure] = $1.strip
        when OPERATION
          Isomorfeus.raise_error(message: 'Operation already defined!') unless operation[:operation].empty?
          operation[:operation] = $1.strip
        when WHITE_SPACE, COMMENT
          # nothing, just skip
        else
          Isomorfeus.raise_error(message: "Unknown key word(s) at the beginning of the line: #{line}") unless operation[:procedure].empty?
          operation[:description] = [] unless operation.key?(:description)
          operation[:description] << line.strip
        end
      end

      operation
    end
  end
end