/*
 * 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.rule;

import static java.util.Arrays.asList;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.ruta.RutaElement;
import org.apache.uima.ruta.RutaStatement;
import org.apache.uima.ruta.RutaStream;
import org.apache.uima.ruta.ScriptApply;
import org.apache.uima.ruta.action.AbstractRutaAction;
import org.apache.uima.ruta.block.RutaBlock;
import org.apache.uima.ruta.condition.AbstractRutaCondition;
import org.apache.uima.ruta.rule.quantifier.NormalQuantifier;
import org.apache.uima.ruta.rule.quantifier.RuleElementQuantifier;
import org.apache.uima.ruta.visitor.InferenceCrowd;

public abstract class AbstractRuleElement extends RutaElement implements RuleElement {

  protected static final InferenceCrowd EMPTY_CROWD = new InferenceCrowd(Collections.emptyList());

  protected RuleElementQuantifier quantifier;

  protected List<AbstractRutaCondition> conditions;

  protected List<AbstractRutaAction> actions;

  private boolean startAnchor;

  private String label;

  private RuleElementContainer container;

  protected RutaBlock parent;

  protected List<List<RutaStatement>> inlinedConditionRuleBlocks = new ArrayList<>();

  protected List<List<RutaStatement>> inlinedActionRuleBlocks = new ArrayList<>();

  public AbstractRuleElement(RuleElementQuantifier quantifier,
          List<AbstractRutaCondition> conditions, List<AbstractRutaAction> actions,
          RuleElementContainer container, RutaBlock parent) {
    super();
    this.quantifier = quantifier;
    this.conditions = conditions;
    this.actions = actions;
    this.container = container;
    this.parent = parent;
    if (this.conditions == null) {
      this.conditions = new ArrayList<>();
    }
    if (this.actions == null) {
      this.actions = new ArrayList<>();
    }
    if (this.quantifier == null) {
      this.quantifier = new NormalQuantifier();
    }
  }

  @Override
  public List<RuleMatch> continueSideStep(boolean after, RuleMatch ruleMatch, RuleApply ruleApply,
          ComposedRuleElementMatch containerMatch, RuleElement entryPoint, RutaStream stream,
          InferenceCrowd crowd) {
    List<RuleMatch> result = new ArrayList<>();
    boolean newDirection = !after;
    List<AnnotationFS> matchedAnnotationsOf = ruleMatch.getMatchedAnnotationsOfElement(this);
    AnnotationFS annotation = null;
    if (!matchedAnnotationsOf.isEmpty()) {
      if (newDirection) {
        annotation = matchedAnnotationsOf.get(matchedAnnotationsOf.size() - 1);
      } else {
        annotation = matchedAnnotationsOf.get(0);
      }
      ComposedRuleElementMatch sideStepContainerMatch = containerMatch;
      if (!containerMatch.getRuleElement().equals(getContainer())) {
        List<List<RuleElementMatch>> matchInfo = ruleMatch
                .getMatchInfo((ComposedRuleElement) getContainer());
        if (newDirection) {
          List<RuleElementMatch> list = matchInfo.get(matchInfo.size() - 1);
          sideStepContainerMatch = (ComposedRuleElementMatch) list.get(list.size() - 1);
        } else {
          List<RuleElementMatch> list = matchInfo.get(0);
          sideStepContainerMatch = (ComposedRuleElementMatch) list.get(0);
        }
      }
      MatchContext context = new MatchContext(this, ruleMatch, newDirection);
      if (quantifier.continueMatch(newDirection, context, annotation, sideStepContainerMatch,
              stream, crowd)) {
        continueMatch(newDirection, annotation, ruleMatch, ruleApply, sideStepContainerMatch, null,
                entryPoint, stream, crowd);
      } else {
        RuleElement nextRuleElement = getContainer().getNextElement(newDirection, this);
        if (nextRuleElement != null) {
          RuleElement sideStepOrigin = null;
          if (getContainer() instanceof RuleElement) {
            sideStepOrigin = (RuleElement) getContainer();
          }
          result = nextRuleElement.continueMatch(newDirection, annotation, ruleMatch, ruleApply,
                  sideStepContainerMatch, sideStepOrigin, entryPoint, stream, crowd);
        } else if (getContainer() instanceof ComposedRuleElement) {
          ComposedRuleElement composed = (ComposedRuleElement) getContainer();
          result = composed.fallbackContinue(newDirection, false, annotation, ruleMatch, ruleApply,
                  sideStepContainerMatch, composed, entryPoint, stream, crowd);
        }
      }
    }
    return result;
  }

  protected void doneMatching(RuleMatch ruleMatch, RuleApply ruleApply, RutaStream stream,
          InferenceCrowd crowd) {
    // do not execute actions if they already have been or if this is just a lookahead
    // (ruleApply==null)
    if (!ruleMatch.isApplied() && ruleApply != null) {
      ruleApply.add(ruleMatch, stream);
      if (ruleMatch.matchedCompletely()) {
        RutaRule rule = ruleMatch.getRule();
        rule.getEnvironment().acceptTempVariableValues(rule.getOwnLabels());
        rule.getRoot().applyRuleElements(ruleMatch, stream, crowd);
      }
      ruleMatch.setApplied(true);
    }
  }

  protected void processInlinedActionRules(RuleMatch ruleMatch, RutaStream stream,
          InferenceCrowd crowd) {
    List<List<RuleElementMatch>> matchInfo = ruleMatch.getMatchInfo(this);
    // TODO: which rule element match should be used? all? should context matter?
    if (matchInfo == null || matchInfo.isEmpty() || matchInfo.get(0) == null
            || matchInfo.get(0).isEmpty()) {
      return;
    }
    RuleElementMatch ruleElementMatch = matchInfo.get(0).get(0);
    processInlinedActionRules(ruleMatch, ruleElementMatch, stream, crowd);
  }

  protected List<List<ScriptApply>> processInlinedActionRules(RuleMatch ruleMatch,
          RuleElementMatch ruleElementMatch, RutaStream stream, InferenceCrowd crowd) {
    if (inlinedActionRuleBlocks != null && !inlinedActionRuleBlocks.isEmpty()) {
      List<List<ScriptApply>> inlinedBlocksApplies = processInlinedRules(inlinedActionRuleBlocks,
              ruleMatch, stream, crowd);
      ruleElementMatch.setInlinedActionRules(inlinedBlocksApplies);
      return inlinedBlocksApplies;
    }
    return null;
  }

  protected List<List<ScriptApply>> processInlinedConditionRules(RuleMatch ruleMatch,
          RuleElementMatch ruleElementMatch, RutaStream stream, InferenceCrowd crowd) {
    if (inlinedConditionRuleBlocks != null && !inlinedConditionRuleBlocks.isEmpty()) {
      List<List<ScriptApply>> inlinedBlocksApplies = processInlinedRules(inlinedConditionRuleBlocks,
              ruleMatch, stream, crowd);
      ruleElementMatch.setInlinedConditionRules(inlinedBlocksApplies);
      return inlinedBlocksApplies;
    }
    return null;
  }

  protected List<List<ScriptApply>> processInlinedRules(List<List<RutaStatement>> inlinedRuleBlocks,
          RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) {
    List<List<ScriptApply>> result = new ArrayList<>();

    List<AnnotationFS> matchedAnnotationsOf = ruleMatch.getMatchedAnnotationsOfElement(this);
    for (AnnotationFS annotationFS : matchedAnnotationsOf) {
      RutaStream windowStream = stream.getWindowStream(annotationFS, annotationFS.getType());
      for (List<RutaStatement> inlinedRules : inlinedRuleBlocks) {
        List<ScriptApply> blockResult = new ArrayList<>();
        for (RutaStatement each : inlinedRules) {
          ScriptApply apply = each.apply(windowStream, crowd);
          blockResult.add(apply);
          if (each instanceof RutaRule) {
            // clean up temp variables produced by failed rules
            ((RutaRule) each).clearOwnLabels();
          }
        }
        result.add(blockResult);
      }
    }

    return result;
  }

  @Override
  public void apply(RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) {
    for (AbstractRutaAction action : actions) {
      crowd.beginVisit(action, null);
      action.execute(new MatchContext(this, ruleMatch), stream, crowd);
      crowd.endVisit(action, null);
    }

    processInlinedActionRules(ruleMatch, stream, crowd);
  }

  protected boolean matchInlinedRules(RuleMatch ruleMatch, RuleElementMatch ruleElementMatch,
          RutaStream stream, InferenceCrowd crowd) {

    List<List<ScriptApply>> blockResults = processInlinedConditionRules(ruleMatch, ruleElementMatch,
            stream, crowd);
    if (blockResults == null) {
      return true;
    }

    boolean matched = true;
    for (List<ScriptApply> list : blockResults) {
      matched &= atLeastOneRuleMatched(list);
    }
    return matched;
  }

  private boolean atLeastOneRuleMatched(List<ScriptApply> list) {
    for (ScriptApply scriptApply : list) {
      if (scriptApply instanceof RuleApply) {
        RuleApply ra = (RuleApply) scriptApply;
        if (ra.applied > 0) {
          return true;
        }
      }
    }
    return false;
  }

  protected List<RuleElementMatch> getMatch(RuleMatch ruleMatch,
          ComposedRuleElementMatch containerMatch) {
    List<RuleElementMatch> matchInfo;
    if (containerMatch != null) {
      matchInfo = containerMatch.getInnerMatches().get(this);
    } else {
      matchInfo = ruleMatch.getMatchInfo(this).get(0);
    }
    return matchInfo;
  }

  @Override
  public List<RuleElementMatch> evaluateMatches(List<RuleElementMatch> matches,
          MatchContext context, RutaStream stream) {
    return quantifier.evaluateMatches(matches, context, stream, EMPTY_CROWD);
  }

  @Override
  public List<Integer> getSelfIndexList() {
    if (getContainer() == null) {
      return null;
    }

    return asList(getContainer().getRuleElements().indexOf(this) + 1);
  }

  @Override
  public boolean hasAncestor(boolean after) {
    RuleElementContainer c = getContainer();
    if (c == null) {
      return false;
    }
    RuleElement nextElement = c.getNextElement(after, this);
    if (nextElement != null) {
      return true;
    }
    if (c instanceof ComposedRuleElement) {
      return ((ComposedRuleElement) c).hasAncestor(after);
    }
    return false;
  }

  protected boolean earlyExit(AnnotationFS eachAnchor, RuleApply ruleApply, RutaStream stream) {
    if (stream.isGreedyAnchoring() && ruleApply != null
            && isAlreadyCovered(eachAnchor, ruleApply, stream)) {
      // skip if next matched should not overlap
      return true;
    }
    if (stream.isOnlyOnce() && ruleApply != null && ruleApply.getApplied() > 0) {
      // skip if the rule should only be applied once, on the first successful match
      return true;
    }
    return false;
  }

  private boolean isAlreadyCovered(AnnotationFS eachAnchor, RuleApply ruleApply,
          RutaStream stream) {
    if (eachAnchor == null) {
      return false;
    }

    List<AbstractRuleMatch<? extends AbstractRule>> list = ruleApply.getList();
    Collections.reverse(list);
    for (AbstractRuleMatch<? extends AbstractRule> each : list) {
      if (each instanceof RuleMatch) {
        RuleMatch rm = (RuleMatch) each;
        List<AnnotationFS> matchedAnnotationsOf = Collections.emptyList();
        if (stream.isGreedyRule()) {
          matchedAnnotationsOf = rm.getMatchedAnnotationsOfRoot();
        } else if (stream.isGreedyRuleElement()) {
          matchedAnnotationsOf = rm.getMatchedAnnotationsOfElement(this);
        }
        for (AnnotationFS annotationFS : matchedAnnotationsOf) {
          if (eachAnchor.getBegin() >= annotationFS.getBegin()
                  && eachAnchor.getEnd() <= annotationFS.getEnd()) {
            return true;
          } else if (eachAnchor.getBegin() < annotationFS.getEnd()) {
            // overlapping annotations of composed rule elements with null ruleApply lookahead
            return true;
          }
        }
      }
    }
    return false;
  }

  @Override
  public RuleElementQuantifier getQuantifier() {
    return quantifier;
  }

  @Override
  public RutaBlock getParent() {
    return parent;
  }

  @Override
  public List<AbstractRutaCondition> getConditions() {
    return conditions;
  }

  public void setConditions(List<AbstractRutaCondition> conditions) {
    this.conditions = conditions;
  }

  @Override
  public List<AbstractRutaAction> getActions() {
    return actions;
  }

  public void setActions(List<AbstractRutaAction> actions) {
    this.actions = actions;
  }

  public void setQuantifier(RuleElementQuantifier quantifier) {
    this.quantifier = quantifier;
  }

  @Override
  public RuleElementContainer getContainer() {
    return container;
  }

  @Override
  public void setContainer(RuleElementContainer container) {
    this.container = container;
  }

  @Override
  public void setStartAnchor(boolean start) {
    startAnchor = start;
  }

  @Override
  public boolean isStartAnchor() {
    return startAnchor;
  }

  @Override
  public String getLabel() {
    return label;
  }

  @Override
  public void setLabel(String label) {
    this.label = label;
  }

  @Override
  public void addInlinedConditionRules(List<RutaStatement> innerRules) {
    inlinedConditionRuleBlocks.add(innerRules);
  }

  @Override
  public List<List<RutaStatement>> getInlinedConditionRuleBlocks() {
    return inlinedConditionRuleBlocks;
  }

  @Override
  public void addInlinedActionRules(List<RutaStatement> innerRules) {
    inlinedActionRuleBlocks.add(innerRules);
  }

  @Override
  public List<List<RutaStatement>> getInlinedActionRuleBlocks() {
    return inlinedActionRuleBlocks;
  }

}
