/*
 * 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.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.cas.FSArray;
import org.apache.uima.ruta.type.DebugBlockApply;
import org.apache.uima.ruta.type.DebugEvaluatedCondition;
import org.apache.uima.ruta.type.DebugInlinedBlock;
import org.apache.uima.ruta.type.DebugRuleApply;
import org.apache.uima.ruta.type.DebugRuleElementMatch;
import org.apache.uima.ruta.type.DebugRuleElementMatches;
import org.apache.uima.ruta.type.DebugRuleMatch;
import org.apache.uima.ruta.type.DebugScriptApply;

public class ExplainTree {

  private IExplainTreeNode root;

  public ExplainTree(JCas jcas) {
    this(jcas, -1);
  }

  public ExplainTree(JCas jcas, int offset) {
    this(jcas, offset, false);
    if (offset >= 0) {
      prune(root);
    }
  }

  public ExplainTree(JCas jcas, int offset, boolean onlyRules) {
    createTree(jcas, offset, onlyRules);
  }

  public IExplainTreeNode getRoot() {
    return root;
  }

  private void createTree(JCas jcas, int offset, boolean onlyRules) {
    TypeSystem ts = jcas.getTypeSystem();
    List<DebugScriptApply> scriptApplies = new ArrayList<>(
            JCasUtil.select(jcas, DebugScriptApply.class));
    // sort by creation time
    Collections.sort(scriptApplies, new Comparator<DebugScriptApply>() {

      @Override
      public int compare(DebugScriptApply o1, DebugScriptApply o2) {
        long l1 = o1.getTimestamp();
        long l2 = o2.getTimestamp();
        return Long.compare(l1, l2);
      }
    });

    root = new ApplyRootNode(null, ts);

    for (DebugScriptApply scriptApply : scriptApplies) {

      buildTree(scriptApply, root, ts, offset, onlyRules);
    }
  }

  private void buildTree(FeatureStructure fs, IExplainTreeNode parent, TypeSystem ts, int offset,
          boolean onlyRules) {
    if (fs instanceof DebugBlockApply) {
      processBlockApply((DebugBlockApply) fs, parent, ts, offset, onlyRules);
    } else if (fs instanceof DebugRuleApply) {
      processRuleApply((DebugRuleApply) fs, parent, ts, offset, onlyRules);
    } else if (fs instanceof DebugRuleMatch) {
      processRuleMatch((DebugRuleMatch) fs, parent, ts, offset, onlyRules);
    } else if (fs instanceof DebugRuleElementMatches) {
      processRuleElementMatches((DebugRuleElementMatches) fs, parent, ts, offset, onlyRules);
    } else if (fs instanceof DebugRuleElementMatch) {
      processRuleElementMatch((DebugRuleElementMatch) fs, parent, ts, offset, onlyRules);
    } else if (fs instanceof DebugEvaluatedCondition) {
      processEvaluatedCondition((DebugEvaluatedCondition) fs, parent, ts, offset, onlyRules);
    }
  }

  private void buildInlinedBlock(boolean asCondition, DebugInlinedBlock debugInlinedBlock,
          IExplainTreeNode parent, TypeSystem ts, int offset, boolean onlyRules) {
    InlinedRuleBlockNode inlinedBlockNode = new InlinedRuleBlockNode(parent, debugInlinedBlock,
            debugInlinedBlock.getAsCondition(), debugInlinedBlock.getMatched(), ts);
    parent.addChild(inlinedBlockNode);

    FSArray inlinedRules = debugInlinedBlock.getInlinedRules();
    if (inlinedRules != null) {
      for (FeatureStructure each : inlinedRules) {
        buildTree(each, inlinedBlockNode, ts, offset, onlyRules);
      }
    }
  }

  private void processBlockApply(DebugBlockApply 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);
    }

    if (fs.getInnerApply() != null) {
      for (FeatureStructure each : fs.getInnerApply()) {
        if (!onlyRules) {
          buildTree(each, blockNode, ts, offset, onlyRules);
        } else {
          buildTree(each, parent, ts, offset, onlyRules);
        }
      }
    }
  }

  private void processBlockRuleApply(DebugBlockApply 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);

    MatchedRootNode matched = new MatchedRootNode(ruleNode, ts);
    FailedRootNode failed = new FailedRootNode(ruleNode, ts);
    ruleNode.addChild(matched);
    ruleNode.addChild(failed);

    if (fs.getRules() != null) {
      for (FeatureStructure each : fs.getRules()) {
        DebugRuleMatch eachRuleMatch = (DebugRuleMatch) each;
        boolean matchedValue = eachRuleMatch.getMatched();
        if (matchedValue) {
          buildTree(eachRuleMatch, matched, ts, offset, onlyRules);
        } else {
          buildTree(eachRuleMatch, failed, ts, offset, onlyRules);
        }
        if (eachRuleMatch.getDelegates() != null) {
          for (FeatureStructure delegateFS : eachRuleMatch.getDelegates()) {
            buildTree(delegateFS, ruleNode, ts, offset, onlyRules);
          }
        }
      }
    }

  }

  private void processRuleApply(DebugRuleApply 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);

    MatchedRootNode matched = new MatchedRootNode(ruleNode, ts);
    FailedRootNode failed = new FailedRootNode(ruleNode, ts);
    ruleNode.addChild(matched);
    ruleNode.addChild(failed);

    if (fs.getRules() != null) {
      for (FeatureStructure each : fs.getRules()) {
        DebugRuleMatch eachRuleMatch = (DebugRuleMatch) each;
        boolean matchedValue = eachRuleMatch.getMatched();
        if (matchedValue) {
          buildTree(eachRuleMatch, matched, ts, offset, onlyRules);
        } else {
          buildTree(eachRuleMatch, failed, ts, offset, onlyRules);
        }
        if (eachRuleMatch.getDelegates() != null) {
          for (FeatureStructure delegateFS : eachRuleMatch.getDelegates()) {
            buildTree(delegateFS, ruleNode, ts, offset, onlyRules);
          }
        }
      }
      if (fs.getRules().size() == 1) {
        mergeInlinedRuleBlockNodesOfChildren(ruleNode);
      }
    }
  }

  private void processRuleMatch(DebugRuleMatch 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);

    if (fs.getElements() != null) {
      for (FeatureStructure each : fs.getElements()) {
        buildTree(each, remRoot, ts, offset, onlyRules);
      }
    }
    mergeInlinedRuleBlockNodesOfChildren(matchNode);
  }

  private void processRuleElementMatches(DebugRuleElementMatches fs, IExplainTreeNode parent,
          TypeSystem ts, int offset, boolean onlyRules) {
    RuleElementMatchesNode remsNode = new RuleElementMatchesNode(parent, fs, ts);
    parent.addChild(remsNode);

    if (fs.getMatches() != null) {
      for (FeatureStructure each : fs.getMatches()) {
        buildTree(each, remsNode, ts, offset, onlyRules);
      }
    }

    FSArray inlinedActionBlocks = fs.getInlinedActionBlocks();
    if (inlinedActionBlocks != null) {
      InlinedRootNode inlinedRootNode = new InlinedRootNode(remsNode, ts);
      remsNode.setInlined(inlinedRootNode);
      for (FeatureStructure each : inlinedActionBlocks) {
        if (each instanceof DebugInlinedBlock) {
          buildInlinedBlock(false, (DebugInlinedBlock) each, inlinedRootNode, ts, offset,
                  onlyRules);
        }
      }
    }
    mergeInlinedRuleBlockNodesOfChildren(remsNode);
  }

  private void processRuleElementMatch(DebugRuleElementMatch 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);

    DebugEvaluatedCondition baseCondition = fs.getBaseCondition();
    buildTree(baseCondition, remNode, ts, offset, onlyRules);

    if (fs.getConditions() != null) {
      for (FeatureStructure each : fs.getConditions()) {
        buildTree(each, remNode, ts, offset, onlyRules);
      }
    }
    if (fs.getElements() != null) {
      for (FeatureStructure each : fs.getElements()) {
        buildTree(each, remNode, ts, offset, onlyRules);
      }
    }
    FSArray inlinedConditionBlocks = fs.getInlinedConditionBlocks();
    if (inlinedConditionBlocks != null) {
      InlinedRootNode inlinedRootNode = new InlinedRootNode(remNode, ts);
      remNode.setInlined(inlinedRootNode);
      for (FeatureStructure each : inlinedConditionBlocks) {
        if (each instanceof DebugInlinedBlock) {
          buildInlinedBlock(true, (DebugInlinedBlock) each, inlinedRootNode, ts, offset, onlyRules);
        }
      }
    }
    mergeInlinedRuleBlockNodesOfChildren(remNode);
  }

  private void processEvaluatedCondition(DebugEvaluatedCondition fs, IExplainTreeNode parent,
          TypeSystem ts, int offset, boolean onlyRules) {
    ConditionNode condNode = new ConditionNode(parent, fs, ts);
    parent.addChild(condNode);

    if (fs.getConditions() != null) {
      for (FeatureStructure each : fs.getConditions()) {
        buildTree(each, condNode, ts, offset, onlyRules);
      }
    }
  }

  private void mergeInlinedRuleBlockNodesOfChildren(ExplainAbstractTreeNode parent) {

    List<IExplainTreeNode> list = new ArrayList<>();

    for (IExplainTreeNode each : parent.getChildren()) {
      collectInlinedBlockNodes(each, list);
    }
    InlinedRootNode inlinedRootNode = parent.getInlined();
    if (inlinedRootNode == null && !list.isEmpty()) {
      inlinedRootNode = new InlinedRootNode(parent, parent.getTypeSystem());
      parent.setInlined(inlinedRootNode);
    }

    if (inlinedRootNode != null) {
      for (IExplainTreeNode each : list) {
        if (!inlinedRootNode.getChildren().contains(each)) {
          inlinedRootNode.addChild(each);
        }
      }
    }
  }

  private void collectInlinedBlockNodes(IExplainTreeNode node, List<IExplainTreeNode> result) {
    if (node.getInlined() != null && node.getInlined().hasChildren()) {
      // already collected down to this level
      result.addAll(node.getInlined().getChildren());
      return;
    }

    List<IExplainTreeNode> children = node.getChildren();
    for (IExplainTreeNode each : children) {
      collectInlinedBlockNodes(each, result);
    }
  }

  private void prune(IExplainTreeNode node) {
    if (node == null) {
      return;
    }
    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) {
    }
  }
}
