/*
 * 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.explain.tree;

import java.util.ArrayList;
import java.util.List;

import org.apache.uima.cas.ArrayFS;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.ruta.explain.ExplainConstants;

public class ExplainTree {

  private IExplainTreeNode root;

  private Type ruleMatchType;

  private Type blockApplyType;

  private Type ruleApplyType;

  private Type ruleElementMatchType;

  private Type ruleElementMatchesType;

  private Type evaluatedConditionType;

  private Type matchedRuleMatchType;

  private Type failedRuleMatchType;

  public ExplainTree(CAS cas) {
    this(cas, -1);
  }

  public ExplainTree(CAS cas, int offset) {
    this(cas, offset, false);
    if (offset >= 0) {
      prune(root);
    }
  }

  public ExplainTree(CAS cas, int offset, boolean onlyRules) {
    createTree(cas, offset, onlyRules);
  }

  public IExplainTreeNode getRoot() {
    return root;
  }

  private void createTree(CAS cas, int offset, boolean onlyRules) {
    TypeSystem ts = cas.getTypeSystem();
    Type scriptApply = ts.getType(ExplainConstants.SCRIPT_APPLY_TYPE);

    blockApplyType = ts.getType(ExplainConstants.BLOCK_APPLY_TYPE);
    ruleApplyType = ts.getType(ExplainConstants.RULE_APPLY_TYPE);
    ruleMatchType = ts.getType(ExplainConstants.RULE_MATCH_TYPE);
    matchedRuleMatchType = ts.getType(ExplainConstants.MATCHED_RULE_MATCH_TYPE);
    failedRuleMatchType = ts.getType(ExplainConstants.FAILED_RULE_MATCH_TYPE);
    ruleElementMatchType = ts.getType(ExplainConstants.RULE_ELEMENT_MATCH_TYPE);
    ruleElementMatchesType = ts.getType(ExplainConstants.RULE_ELEMENT_MATCHES_TYPE);
    evaluatedConditionType = ts.getType(ExplainConstants.EVAL_CONDITION_TYPE);

    if (scriptApply == null)
      return;
    FSIterator<AnnotationFS> it = cas.getAnnotationIndex(scriptApply).iterator();
    root = new ApplyRootNode(null, ts);

    if (it.isValid()) {
      it.moveToFirst();
      while (it.isValid()) {
        AnnotationFS fs = it.get();
        buildTree(fs, root, ts, offset, onlyRules);
        it.moveToNext();
      }
    }

  }

  private void buildTree(FeatureStructure fs, IExplainTreeNode parent, TypeSystem ts, int offset,
          boolean onlyRules) {
    if (blockApplyType != null && blockApplyType.equals(fs.getType())) {
      processBlockApply((AnnotationFS) fs, parent, ts, offset, onlyRules);
    } else if (ruleApplyType != null && ruleApplyType.equals(fs.getType())) {
      processRuleApply((AnnotationFS) fs, parent, ts, offset, onlyRules);
    } else if ((matchedRuleMatchType != null && matchedRuleMatchType.equals(fs.getType()))
            || (failedRuleMatchType != null && failedRuleMatchType.equals(fs.getType()))) {
      processRuleMatch((AnnotationFS) fs, parent, ts, offset, onlyRules);
    } else if (ruleElementMatchesType != null && ruleElementMatchesType.equals(fs.getType())) {
      processRuleElementMatches(fs, parent, ts, offset, onlyRules);
    } else if (ruleElementMatchType != null && ruleElementMatchType.equals(fs.getType())) {
      processRuleElementMatch((AnnotationFS) fs, parent, ts, offset, onlyRules);
    } else if (evaluatedConditionType != null && evaluatedConditionType.equals(fs.getType())) {
      processEvaluatedCondition(fs, parent, ts, offset, onlyRules);
    }
  }

  private void processBlockApply(AnnotationFS fs, IExplainTreeNode parent, TypeSystem ts,
          int offset, boolean onlyRules) {
    if (offset >= 0 && (fs.getBegin() >= offset || fs.getEnd() <= offset)) {
      return;
    }
    BlockApplyNode blockNode = null;
    if (!onlyRules) {
      blockNode = new BlockApplyNode(parent, fs, ts);
      parent.addChild(blockNode);
      processBlockRuleApply(fs, blockNode, ts, offset, onlyRules);
    }
    Feature feature = blockApplyType.getFeatureByBaseName(ExplainConstants.INNER_APPLY);
    FeatureStructure featureValue = fs.getFeatureValue(feature);
    ArrayFS value = (ArrayFS) featureValue;
    FeatureStructure[] fsarray = value.toArray();
    for (FeatureStructure each : fsarray) {
      if (!onlyRules) {
        buildTree(each, blockNode, ts, offset, onlyRules);
      } else {
        buildTree(each, parent, ts, offset, onlyRules);
      }

    }
  }

  private void processBlockRuleApply(AnnotationFS fs, BlockApplyNode parent, TypeSystem ts,
          int offset, boolean onlyRules) {
    if (offset >= 0 && (fs.getBegin() >= offset || fs.getEnd() <= offset)) {
      return;
    }
    RuleApplyNode ruleNode = new RuleApplyNode(parent, fs, ts);
    parent.setBlockRuleApply(ruleNode);

    Feature feature = ruleApplyType.getFeatureByBaseName(ExplainConstants.RULES);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    if (value == null)
      return;
    FeatureStructure[] fsarray = value.toArray();

    MatchedRootNode matched = new MatchedRootNode(ruleNode, ts);
    FailedRootNode failed = new FailedRootNode(ruleNode, ts);
    ruleNode.addChild(matched);
    ruleNode.addChild(failed);

    for (FeatureStructure eachRuleMatch : fsarray) {
      Feature f = eachRuleMatch.getType().getFeatureByBaseName(ExplainConstants.MATCHED);
      boolean matchedValue = eachRuleMatch.getBooleanValue(f);
      if (matchedValue) {
        buildTree(eachRuleMatch, matched, ts, offset, onlyRules);
      } else {
        buildTree(eachRuleMatch, failed, ts, offset, onlyRules);
      }

      Feature df = eachRuleMatch.getType().getFeatureByBaseName(ExplainConstants.DELEGATES);
      if (df != null) {
        ArrayFS dv = (ArrayFS) eachRuleMatch.getFeatureValue(df);
        if (dv != null) {
          FeatureStructure[] da = dv.toArray();
          for (FeatureStructure delegateFS : da) {
            buildTree(delegateFS, ruleNode, ts, offset, onlyRules);
          }
        }
      }

    }
  }

  private void processRuleApply(AnnotationFS fs, IExplainTreeNode parent, TypeSystem ts,
          int offset, boolean onlyRules) {
    if (offset >= 0 && (fs.getBegin() >= offset || fs.getEnd() <= offset)) {
      return;
    }
    RuleApplyNode ruleNode = new RuleApplyNode(parent, fs, ts);
    parent.addChild(ruleNode);

    Feature feature = ruleApplyType.getFeatureByBaseName(ExplainConstants.RULES);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    FeatureStructure[] fsarray = value.toArray();

    MatchedRootNode matched = new MatchedRootNode(ruleNode, ts);
    FailedRootNode failed = new FailedRootNode(ruleNode, ts);
    ruleNode.addChild(matched);
    ruleNode.addChild(failed);

    for (FeatureStructure eachRuleMatch : fsarray) {
      Feature f = eachRuleMatch.getType().getFeatureByBaseName(ExplainConstants.MATCHED);
      boolean matchedValue = eachRuleMatch.getBooleanValue(f);
      if (matchedValue) {
        buildTree(eachRuleMatch, matched, ts, offset, onlyRules);
      } else {
        buildTree(eachRuleMatch, failed, ts, offset, onlyRules);
      }

      Feature df = eachRuleMatch.getType().getFeatureByBaseName(ExplainConstants.DELEGATES);
      if (df != null) {
        ArrayFS dv = (ArrayFS) eachRuleMatch.getFeatureValue(df);
        if (dv != null) {
          FeatureStructure[] da = dv.toArray();
          for (FeatureStructure delegateFS : da) {
            buildTree(delegateFS, ruleNode, ts, offset, onlyRules);
          }
        }
      }

    }
  }

  private void processRuleMatch(AnnotationFS fs, IExplainTreeNode parent, TypeSystem ts,
          int offset, boolean onlyRules) {
    if (offset >= 0 && (fs.getBegin() >= offset || fs.getEnd() <= offset)) {
      return;
    }
    RuleMatchNode matchNode = new RuleMatchNode(parent, fs, ts);
    parent.addChild(matchNode);

    RuleElementRootNode remRoot = new RuleElementRootNode(matchNode, ts);
    matchNode.addChild(remRoot);

    Feature feature = ruleMatchType.getFeatureByBaseName(ExplainConstants.ELEMENTS);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    if (value != null) {
      FeatureStructure[] fsarray = value.toArray();
      for (FeatureStructure each : fsarray) {
        buildTree(each, remRoot, ts, offset, onlyRules);
      }
    }
  }

  private void processRuleElementMatches(FeatureStructure fs, IExplainTreeNode parent,
          TypeSystem ts, int offset, boolean onlyRules) {
    RuleElementMatchesNode remsNode = new RuleElementMatchesNode(parent, fs, ts);
    parent.addChild(remsNode);

    Feature feature = ruleElementMatchesType.getFeatureByBaseName(ExplainConstants.MATCHES);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    FeatureStructure[] fsarray = value.toArray();
    for (FeatureStructure each : fsarray) {
      buildTree(each, remsNode, ts, offset, onlyRules);
    }
  }

  private void processRuleElementMatch(AnnotationFS fs, IExplainTreeNode parent, TypeSystem ts,
          int offset, boolean onlyRules) {
    if (offset >= 0 && (fs.getBegin() >= offset || fs.getEnd() <= offset)) {
      return;
    }
    RuleElementMatchNode remNode = new RuleElementMatchNode(parent, fs, ts);
    parent.addChild(remNode);

    Feature feature = ruleElementMatchType.getFeatureByBaseName(ExplainConstants.BASE_CONDITION);
    FeatureStructure base = fs.getFeatureValue(feature);
    buildTree(base, remNode, ts, offset, onlyRules);

    feature = ruleElementMatchType.getFeatureByBaseName(ExplainConstants.CONDITIONS);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    if (value != null) {
      FeatureStructure[] fsarray = value.toArray();
      for (FeatureStructure each : fsarray) {
        buildTree(each, remNode, ts, offset, onlyRules);
      }
    }
    feature = fs.getType().getFeatureByBaseName(ExplainConstants.ELEMENTS);
    value = (ArrayFS) fs.getFeatureValue(feature);
    if (value != null) {
      FeatureStructure[] fsarray = value.toArray();
      for (FeatureStructure each : fsarray) {
        buildTree(each, remNode, ts, offset, onlyRules);
      }
    }
  }

  private void processEvaluatedCondition(FeatureStructure fs, IExplainTreeNode parent,
          TypeSystem ts, int offset, boolean onlyRules) {
    ConditionNode condNode = new ConditionNode(parent, fs, ts);
    parent.addChild(condNode);

    Feature feature = evaluatedConditionType.getFeatureByBaseName(ExplainConstants.CONDITIONS);
    ArrayFS value = (ArrayFS) fs.getFeatureValue(feature);
    if (value != null) {
      FeatureStructure[] fsarray = value.toArray();
      for (FeatureStructure each : fsarray) {
        buildTree(each, condNode, ts, offset, onlyRules);
      }
    }
  }

  private void prune(IExplainTreeNode node) {
    List<IExplainTreeNode> children = node.getChildren();
    IExplainTreeNode parent = node.getParent();
    for (IExplainTreeNode each : new ArrayList<IExplainTreeNode>(children)) {
      prune(each);
    }
    if (node instanceof ApplyRootNode) {
    } else if (node instanceof BlockApplyNode) {
    } else if (node instanceof ConditionNode) {
    } else if (node instanceof FailedRootNode) {
      if (!node.hasChildren()) {
        parent.removeChild(node);
      }
    } else if (node instanceof MatchedRootNode) {
      if (!node.hasChildren()) {
        parent.removeChild(node);
      }
    } else if (node instanceof RuleApplyNode) {
      if (!node.hasChildren()) {
        parent.removeChild(node);
      }
    } else if (node instanceof RuleElementMatchesNode) {
    } else if (node instanceof RuleElementMatchNode) {
    } else if (node instanceof RuleElementRootNode) {
    } else if (node instanceof RuleMatchNode) {
    }
  }
}
