/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.calcite.runtime;

import org.apache.calcite.runtime.Automaton.EpsilonTransition;
import org.apache.calcite.runtime.Automaton.State;
import org.apache.calcite.runtime.Automaton.SymbolTransition;
import org.apache.calcite.runtime.Automaton.Transition;

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;

/** Builds a state-transition graph for deterministic finite automaton. */
public class AutomatonBuilder {
  private final Map<String, Integer> symbolIds = new HashMap<>();
  private final List<State> stateList = new ArrayList<>();
  private final List<Transition> transitionList = new ArrayList<>();
  @SuppressWarnings("method.invocation.invalid")
  private final State startState = createState();
  @SuppressWarnings("method.invocation.invalid")
  private final State endState = createState();

  /** Adds a pattern as a start-to-end transition. */
  AutomatonBuilder add(Pattern pattern) {
    return add(pattern, startState, endState);
  }

  private AutomatonBuilder add(Pattern pattern, State fromState,
      State toState) {
    final Pattern.AbstractPattern p = (Pattern.AbstractPattern) pattern;
    switch (p.op) {
    case SEQ:
      final Pattern.OpPattern pSeq = (Pattern.OpPattern) p;
      return seq(fromState, toState, pSeq.patterns);

    case STAR:
      final Pattern.OpPattern pStar = (Pattern.OpPattern) p;
      return star(fromState, toState, pStar.patterns.get(0));

    case PLUS:
      final Pattern.OpPattern pPlus = (Pattern.OpPattern) p;
      return plus(fromState, toState, pPlus.patterns.get(0));

    case REPEAT:
      final Pattern.RepeatPattern pRepeat = (Pattern.RepeatPattern) p;
      return repeat(fromState, toState, pRepeat.patterns.get(0),
          pRepeat.minRepeat, pRepeat.maxRepeat);

    case SYMBOL:
      final Pattern.SymbolPattern pSymbol = (Pattern.SymbolPattern) p;
      return symbol(fromState, toState, pSymbol.name);

    case OR:
      final Pattern.OpPattern pOr = (Pattern.OpPattern) p;
      return or(fromState, toState, pOr.patterns.get(0), pOr.patterns.get(1));

    case OPTIONAL:
      // Rewrite as {0,1}
      final Pattern.OpPattern pOptional = (Pattern.OpPattern) p;
      return optional(fromState, toState, pOptional.patterns.get(0));

    default:
      throw new AssertionError("unknown op " + p.op);
    }
  }

  private State createState() {
    final State state = new State(stateList.size());
    stateList.add(state);
    return state;
  }

  /** Builds the automaton. */
  public Automaton build() {
    final ImmutableList.Builder<SymbolTransition> symbolTransitions =
        ImmutableList.builder();
    final ImmutableList.Builder<EpsilonTransition> epsilonTransitions =
        ImmutableList.builder();
    for (Transition transition : transitionList) {
      if (transition instanceof SymbolTransition) {
        symbolTransitions.add((SymbolTransition) transition);
      }
      if (transition instanceof EpsilonTransition) {
        epsilonTransitions.add((EpsilonTransition) transition);
      }
    }
    // Sort the symbols by their ids, which are assumed consecutive and
    // starting from zero.
    final ImmutableList<String> symbolNames = symbolIds.entrySet()
        .stream()
        .sorted(Comparator.comparingInt(Map.Entry::getValue))
        .map(Map.Entry::getKey)
        .collect(toImmutableList());
    return new Automaton(stateList.get(0), endState,
        symbolTransitions.build(), epsilonTransitions.build(), symbolNames);
  }

  /** Adds a symbol transition. */
  AutomatonBuilder symbol(State fromState, State toState,
      String name) {
    Objects.requireNonNull(name, "name");
    final int symbolId =
        symbolIds.computeIfAbsent(name, k -> symbolIds.size());
    transitionList.add(new SymbolTransition(fromState, toState, symbolId));
    return this;
  }

  /** Adds a transition made up of a sequence of patterns. */
  AutomatonBuilder seq(State fromState, State toState,
      List<Pattern> patterns) {
    State prevState = fromState;
    for (int i = 0; i < patterns.size(); i++) {
      Pattern pattern = patterns.get(i);
      final State nextState;
      if (i == patterns.size() - 1) {
        nextState = toState;
      } else {
        nextState = createState();
      }
      add(pattern, prevState, nextState);
      prevState = nextState;
    }
    return this;
  }

  /** Adds a transition for the 'or' pattern. */
  AutomatonBuilder or(State fromState, State toState, Pattern left,
      Pattern right) {
    //
    //             left
    //         / -------->  toState
    //  fromState
    //         \ --------> toState
    //             right

    add(left, fromState, toState);
    add(right, fromState, toState);
    return this;
  }

  /** Adds a transition made up of the Kleene star applied to a pattern. */
  AutomatonBuilder star(State fromState, State toState, Pattern pattern) {
    //
    //     +------------------------- e ------------------------+
    //     |                +-------- e -------+                |
    //     |                |                  |                |
    //     |                V                  |                V
    // fromState -----> beforeState -----> afterState -----> toState
    //             e               pattern              e
    //
    final State beforeState = createState();
    final State afterState = createState();
    transitionList.add(new EpsilonTransition(fromState, beforeState));
    add(pattern, beforeState, afterState);
    transitionList.add(new EpsilonTransition(afterState, beforeState));
    transitionList.add(new EpsilonTransition(afterState, toState));
    transitionList.add(new EpsilonTransition(fromState, toState));
    return this;
  }

  /** Adds a transition made up of a pattern repeated 1 or more times. */
  AutomatonBuilder plus(State fromState, State toState, Pattern pattern) {
    //
    //                      +-------- e -------+
    //                      |                  |
    //                      V                  |
    // fromState -----> beforeState -----> afterState -----> toState
    //             e               pattern              e
    //
    final State beforeState = createState();
    final State afterState = createState();
    transitionList.add(new EpsilonTransition(fromState, beforeState));
    add(pattern, beforeState, afterState);
    transitionList.add(new EpsilonTransition(afterState, beforeState));
    transitionList.add(new EpsilonTransition(afterState, toState));
    return this;
  }

  /** Adds a transition made up of a pattern repeated between {@code minRepeat}
   * and {@code maxRepeat} times. */
  AutomatonBuilder repeat(State fromState, State toState, Pattern pattern,
      int minRepeat, int maxRepeat) {
    // Diagram for repeat(1, 3)
    //                              +-------- e --------------+
    //                              |           +---- e ----+ |
    //                              |           |           V V
    // fromState ---> state0 ---> state1 ---> state2 ---> state3 ---> toState
    //            e        pattern     pattern     pattern        e
    //
    checkArgument(0 <= minRepeat);
    checkArgument(minRepeat <= maxRepeat);
    checkArgument(1 <= maxRepeat);
    State prevState = fromState;
    for (int i = 0; i <= maxRepeat; i++) {
      final State s = createState();
      if (i == 0) {
        transitionList.add(new EpsilonTransition(fromState, s));
      } else {
        add(pattern, prevState, s);
      }
      if (i >= minRepeat) {
        transitionList.add(new EpsilonTransition(s, toState));
      }
      prevState = s;
    }
    transitionList.add(new EpsilonTransition(prevState, toState));
    return this;
  }

  private AutomatonBuilder optional(State fromState, State toState, Pattern pattern) {
    add(pattern, fromState, toState);
    transitionList.add(new EpsilonTransition(fromState, toState));
    return this;
  }
}
