/*
 * 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.uima.ruta.block.fst;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.ruta.RutaStatement;
import org.apache.uima.ruta.RutaStream;
import org.apache.uima.ruta.block.RutaBlock;
import org.apache.uima.ruta.condition.AbstractRutaCondition;
import org.apache.uima.ruta.rule.ComposedRuleElementMatch;
import org.apache.uima.ruta.rule.EvaluatedCondition;
import org.apache.uima.ruta.rule.MatchContext;
import org.apache.uima.ruta.rule.RuleElement;
import org.apache.uima.ruta.rule.RuleElementMatch;
import org.apache.uima.ruta.rule.RuleMatch;
import org.apache.uima.ruta.rule.RutaMatcher;
import org.apache.uima.ruta.rule.RutaRule;
import org.apache.uima.ruta.rule.RutaRuleElement;
import org.apache.uima.ruta.verbalize.RutaVerbalizer;
import org.apache.uima.ruta.visitor.InferenceCrowd;

public class Automaton {

  private RutaVerbalizer verbalizer;

  private RootState root;

  /**
   * Constructor that builds the FST from the Rules in rulesList
   * 
   * @param rulesList
   *          - the rules to build the FST from
   */
  public Automaton(List<RutaStatement> rulesList) {
    this.verbalizer = new RutaVerbalizer();
    this.root = this.buildAutomaton(rulesList);
  }

  /**
   * Builds the FST from the Rules in rulesList.
   * 
   * @param rulesList
   *          - the rules to build the FST from
   * @return the RootState for the built FST
   */
  public RootState buildAutomaton(List<RutaStatement> rulesList) {
    RootState root = new RootState();
    for (RutaStatement statement : rulesList) {
      AbstractState startState = root;
      if (statement instanceof RutaRule) {
        RutaRule rule = (RutaRule) statement;
        int depth = 1;
        for (RuleElement element : rule.getRuleElements()) {
          AbstractState targetState = null;
          for (RuleElement toCompare : startState.getPossibleTransitions()) {
            if (ruleElementEquals(element, toCompare)) {
              targetState = startState.getTransition(toCompare);
            }
            if (targetState instanceof EndState) {
              // Falls zwei Regeln genau gleich, erstelle trotzdem
              // zwei verschiedene Endzustände
              targetState = null;
            }
          }
          if (targetState == null) { // Erstelle neuen Zielzustand
            if (depth == rule.getRuleElements().size()) {
              targetState = new EndState(statement, depth);
            } else {
              targetState = new TransitionState(depth);
              ((TransitionState) targetState).addRule(statement);
            }
            startState.addTransition(element, targetState);
          } else { // Benutze existierenden Zielzustand
            if (targetState instanceof TransitionState) {
              ((TransitionState) targetState).addRule(statement);
            }
          }
          startState = targetState;
          depth++;
        }
      }
    }
    return root;
  }

  /**
   * Compares two RuleElements. They are if their verbalization, e. g. "CW" or "SW" is equal, not if
   * elem1 == elem2 or elem1.equals(elem2)
   * 
   * @param elem1
   *          - The first RuleElement to compare
   * @param elem2
   *          - The second RuleElement to compare
   * 
   * @return true if the verbalization of the two RuleElements equals, else false
   */
  public boolean ruleElementEquals(RuleElement elem1, RuleElement elem2) {
    return verbalizer.verbalize(elem1).equals(verbalizer.verbalize(elem2));
  }

  /**
   * Starts the execution of the Automaton in the rootState
   * 
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * @param parent
   *          - the RutaBlock (is needed in called functions)
   */
  public void apply(RutaStream stream, InferenceCrowd crowd, RutaBlock parent) {
    for (RuleElement element : root.getPossibleTransitions()) {
      AbstractState targetState = root.getTransition(element);
      RutaMatcher matcher = ((RutaRuleElement) element).getMatcher();
      for (AnnotationFS annoFS : matcher.getMatchingAnnotations(parent, stream)) {
        if (targetState instanceof TransitionState) {
          LinkedList<RuleMatch> ruleMatches = createMatches(annoFS,
                  ((TransitionState) targetState).getRules(), stream, crowd);
          doTransition((TransitionState) targetState, annoFS, element, ruleMatches, stream, crowd,
                  parent);
        } else {
          RuleMatch ruleMatch = createMatch(annoFS, (RutaRule) ((EndState) targetState).getRule(),
                  stream, crowd);
          addAnnotation((EndState) targetState, ruleMatch, stream, crowd);
        }
      }
    }
  }

  /**
   * Pursues the execution of the Automaton in the next state.
   * 
   * @param startState
   *          - the state to go on from
   * @param anno
   *          - the matched Annotation from the previous transition
   * @param ruleElement
   *          - the last matched RuleElement
   * @param matches
   *          - the list of RuleMatches corresponding to the rules in the state
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * @param parent
   *          - the RutaBlock (is needed in called functions)
   */
  private void doTransition(TransitionState startState, AnnotationFS anno, RuleElement ruleElement,
          LinkedList<RuleMatch> matches, RutaStream stream, InferenceCrowd crowd,
          RutaBlock parent) {
    for (RuleElement element : startState.getPossibleTransitions()) {
      RutaMatcher matcher = ((RutaRuleElement) element).getMatcher();
      AbstractState targetState = startState.getTransition(element);
      for (AnnotationFS annoFS : matcher.getAnnotationsAfter((RutaRuleElement) ruleElement, anno,
              parent, stream)) {
        if (targetState instanceof TransitionState) {
          LinkedList<RuleMatch> ruleMatches = filterMatches(annoFS, matches,
                  (TransitionState) targetState, stream, crowd);
          doTransition((TransitionState) targetState, annoFS, element, ruleMatches, stream, crowd,
                  parent);
        } else {
          RuleMatch ruleMatch = filterMatch(annoFS, matches, (EndState) targetState, stream, crowd);
          addAnnotation((EndState) targetState, ruleMatch, stream, crowd);
        }
      }
    }
  }

  /**
   * Creates the Annotation after a full matching of a rule, this means the FST reached an EndState
   * 
   * 
   * @param targetState
   *          - the reached Endstate representing the rule
   * @param ruleMatch
   *          - the RuleMatch corresponding the Rule
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   */
  public void addAnnotation(EndState targetState, RuleMatch ruleMatch, RutaStream stream,
          InferenceCrowd crowd) {
    RutaStatement statement = targetState.getRule();
    if (statement instanceof RutaRule) {
      RutaRule rule = (RutaRule) statement;
      rule.getRoot().apply(ruleMatch, stream, crowd);
    }
  }

  /**
   * Checks the matching of the annotation and updates the RuleMatch
   * 
   * @param annotation
   *          - the matched Annotation
   * @param ruleMatch
   *          - the RuleMatch to update
   * @param element
   *          - the matched RuleElement
   * @param containerMatch
   *          - the ComposedRuleElement of the rule containing element
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   */
  private void doMatch(AnnotationFS annotation, RuleMatch ruleMatch, RuleElement element,
          ComposedRuleElementMatch containerMatch, RutaStream stream, InferenceCrowd crowd) {
    RuleElementMatch result = new RuleElementMatch(element, containerMatch);
    List<EvaluatedCondition> evaluatedConditions = new ArrayList<EvaluatedCondition>(
            element.getConditions().size());
    // boolean base = matcher.match(annotation, stream, getParent());
    boolean base = true;
    MatchContext context = new MatchContext(annotation, element, ruleMatch, true);

    List<AnnotationFS> textsMatched = new ArrayList<AnnotationFS>(1);
    if (annotation != null) {
      textsMatched.add(annotation);
    }
    result.setMatchInfo(base, textsMatched, stream);
    if (base) {
      for (AbstractRutaCondition condition : element.getConditions()) {
        crowd.beginVisit(condition, null);
        EvaluatedCondition eval = condition.eval(context, stream, crowd);
        crowd.endVisit(condition, null);
        evaluatedConditions.add(eval);
      }
    }
    if (annotation != null) {
      textsMatched.add(annotation);
    }
    result.setConditionInfo(base, evaluatedConditions);
    ruleMatch.setMatched(ruleMatch.matched() && result.matched());
  }

  /**
   * Creates a list of RuleMatches with one RuleMatch with the annotation for every rule for a
   * transition from the RootState into a TransitionState
   * 
   * @param annoFS
   *          - the matched annotation
   * @param rulesList
   *          - the list of rules
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * 
   * @return - a list with the created RuleMatches
   */
  private LinkedList<RuleMatch> createMatches(AnnotationFS annoFS, List<RutaStatement> rulesList,
          RutaStream stream, InferenceCrowd crowd) {
    // RootState -> TransitionState
    LinkedList<RuleMatch> ruleMatches = new LinkedList<RuleMatch>();
    for (RutaStatement statement : rulesList) {
      RutaRule rule = (RutaRule) statement;
      RuleElement element = rule.getRuleElements().get(0);
      RuleMatch match = new RuleMatch(rule);
      ComposedRuleElementMatch rootMatch = new ComposedRuleElementMatch(rule.getRoot(), null);
      match.setRootMatch(rootMatch);
      doMatch(annoFS, match, element, rootMatch, stream, crowd);
      ruleMatches.add(match);
    }
    return ruleMatches;
  }

  /**
   * Creates the match for the transition from the RootState directly into an EndState (happens if
   * the rule only has one RuleElement).
   * 
   * @param annoFS
   *          - the matches annotation for the RuleMatch
   * @param rule
   *          - the matched rule for the RuleMatch
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * 
   * @return the created RuleMatch for the rule with the matched annotation
   */
  private RuleMatch createMatch(AnnotationFS annoFS, RutaRule rule, RutaStream stream,
          InferenceCrowd crowd) {
    // RootState -> EndState
    RuleElement element = rule.getRuleElements().get(0);
    RuleMatch match = new RuleMatch(rule);
    ComposedRuleElementMatch rootMatch = new ComposedRuleElementMatch(rule.getRoot(), null);
    match.setRootMatch(rootMatch);
    doMatch(annoFS, match, element, rootMatch, stream, crowd);
    return match;
  }

  /**
   * Filters the rules for a transition from a TransitionState into a TransitionState and adds an
   * InnerMatch for the matched Annotationen to the corresponding RuleMatches
   * 
   * @param annoFS
   *          - the matched Annotation
   * @param ruleMatches
   *          - the RuleMatches which are filtered
   * @param targetState
   *          - the TransitionState for which the RuleMatches are filtered
   * @param stream
   *          - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * 
   * @return the RuleMatches for the Rules which are represented by the TransitionState targetState
   */
  private LinkedList<RuleMatch> filterMatches(AnnotationFS annoFS,
          LinkedList<RuleMatch> ruleMatches, TransitionState targetState, RutaStream stream,
          InferenceCrowd crowd) {
    // TransitionState -> TransitionState
    LinkedList<RuleMatch> retList = new LinkedList<RuleMatch>();
    for (RuleMatch match : ruleMatches) {
      for (RutaStatement statement : targetState.getRules()) {
        RutaRule rule = (RutaRule) statement;
        if (match.getRule().equals(rule)) {
          RuleElement element = rule.getRuleElements().get(targetState.getDepth() - 1);
          doMatch(annoFS, match, element, match.getRootMatch(), stream, crowd);
          retList.add(match);
        }
      }
    }
    return retList;
  }

  /**
   * Filters the one RuleMatch from the list of RuleMatches, which corresponds to the Rule from the
   * EndState state and adds the Annotation to the list of matched Annotation of this RuleMatch
   * 
   * @param annoFS
   *          - the Annotation to add
   * @param ruleMatches
   *          - the list of RuleMatches to filter the single RuleMatch from
   * @param state
   *          - the state the rule gets taken from
   * @param stream
   *          stream - the RutaStream (is needed in the called functions)
   * @param crowd
   *          - the InferenceCrowd (is needed in the called functions)
   * 
   * @return the single RuleMatch corresponding to the rule from the state
   */
  private RuleMatch filterMatch(AnnotationFS annoFS, LinkedList<RuleMatch> ruleMatches,
          EndState state, RutaStream stream, InferenceCrowd crowd) {
    // TransitionState -> EndState
    RutaRule rule = (RutaRule) state.getRule();
    for (RuleMatch match : ruleMatches) {
      if (rule.equals(match.getRule())) {
        RuleElement element = rule.getRuleElements().get(state.getDepth() - 1);
        doMatch(annoFS, match, element, match.getRootMatch(), stream, crowd);
        return match;
      }
    }
    // Should not happen!
    return ruleMatches.get(0);
  }
}
