/*
 * 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.myfaces.tobago.model;

import javax.swing.tree.TreeNode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Manages the expanded state of an tree.
 *
 * @since 2.0.0
 */
public class ExpandedState implements Serializable {

  private int defaultExpandedLevels;
  private Set<TreePath> expandedSet;
  private Set<TreePath> collapsedSet;

  /**
   * Creates a new state object to store which nodes of a tree are expanded and collapsed in a view.
   *
   * @param defaultExpandedLevels All nodes up to this level are expanded by default.
   */
  public ExpandedState(final int defaultExpandedLevels) {
    this.defaultExpandedLevels = defaultExpandedLevels;
    this.expandedSet = new HashSet<>();
    this.collapsedSet = new HashSet<>();
  }

  /**
   * Checks if a node is expanded.
   *
   * @param node The node to check.
   * @return Is the node expanded?
   */
  public boolean isExpanded(final TreeNode node) {
    final TreePath path = new TreePath(node);
    return isExpanded(path);
  }

  /**
   * Checks if a node is expanded.
   *
   * @param path The path of the node to check.
   * @return Is the node behind this path is expanded?
   */
  public boolean isExpanded(final TreePath path) {
    if (expandedSet.contains(path)) {
      return true;
    }
    if (collapsedSet.contains(path)) {
      return false;
    }
    return path.getLength() < defaultExpandedLevels;
  }

  /**
   * Expands a single node.
   *
   * @param node The node to expand. Also the parents will be expanded since Tobago 3.0.0.
   */
  public void expand(final TreeNode node) {
    expand(node, true);
  }

  /**
   * Expands a single node.
   *
   * @param node The node to expand.
   * @param parents Should the parents also be expanded?
   */
  public void expand(final TreeNode node, final boolean parents) {
    final TreePath path = new TreePath(node);
    expand(path, parents);
  }

  /**
   * Expands a single node.
   *
   * @param path The path of the node to expand. Also the parents will be expanded since Tobago 3.0.0.
   */
  public void expand(final TreePath path) {
    expand(path, true);
  }

  /**
   * Expands a single node.
   *
   * @param path The path of the node to expand.
   * @param parents Should the parents also be expanded?
   */
  public void expand(final TreePath path, final boolean parents) {
    if (path.getLength() >= defaultExpandedLevels) {
      expandedSet.add(path);
    } else {
      collapsedSet.remove(path);
    }
    if (parents && !path.isRoot()) {
      expand(path.getParent(), true);
    }
  }

  /**
   * Expands all nodes that level are lower or equals the parameter level.
   *
   * @param level The level to expand.
   */
  public void expand(final int level) {
    final ArrayList<TreePath> toRemove = new ArrayList<>();
    if (level > defaultExpandedLevels) {
      defaultExpandedLevels = level;
      for (final TreePath treePath : expandedSet) {
        if (treePath.getLength() < defaultExpandedLevels) {
          toRemove.add(treePath);
        }
      }
      expandedSet.removeAll(toRemove);
      collapsedSet.clear();
    } else {
      for (final TreePath treePath : collapsedSet) {
        if (treePath.getLength() < level) {
          toRemove.add(treePath);
        }
      }
      collapsedSet.removeAll(toRemove);
    }
  }

  /**
   * Expands a nodes of the tree.
   */
  public void expandAll() {
    defaultExpandedLevels = Integer.MAX_VALUE;
    expandedSet.clear();
    collapsedSet.clear();
  }

  /**
   * Collapses a single node.
   *
   * @param node The node to collapse.
   */
  public void collapse(final TreeNode node) {
    final TreePath path = new TreePath(node);
    collapse(path);
  }

  /**
   * Collapses a single node.
   *
   * @param path The path of the node to collapse.
   */
  public void collapse(final TreePath path) {
    if (path.getLength() < defaultExpandedLevels) {
      collapsedSet.add(path);
    } else {
      expandedSet.remove(path);
    }
  }

  /**
   * Collapses all nodes that level are higher or equals the parameter level.
   *
   * @param level The level to expand.
   */
  public void collapse(final int level) {
    int count = level;
    // to use a symmetric algorithm like in expand
    count--;

    final ArrayList<TreePath> toRemove = new ArrayList<>();
    if (count < defaultExpandedLevels) {
      defaultExpandedLevels = count;
      for (final TreePath treePath : collapsedSet) {
        if (treePath.getLength() >= defaultExpandedLevels) {
          toRemove.add(treePath);
        }
      }
      collapsedSet.removeAll(toRemove);
      expandedSet.clear();
    } else {
      for (final TreePath treePath : expandedSet) {
        if (treePath.getLength() >= count) {
          toRemove.add(treePath);
        }
      }
      expandedSet.removeAll(toRemove);
    }
  }

  /**
   * Collapses a nodes of the tree.
   */
  public void collapseAll() {
    defaultExpandedLevels = 0;
    expandedSet.clear();
    collapsedSet.clear();
  }

  /**
   * Collapses a nodes of the tree. The root node will be expanded.
   */
  public void collapseAllButRoot() {
    defaultExpandedLevels = 1;
    expandedSet.clear();
    collapsedSet.clear();
  }

  /**
   * Resets the state to the defaults. After this call, the nodes with level smaller than defaultExpandedLevels
   * are expanded, the other ones are collapsed.
   */
  public void reset() {
    expandedSet.clear();
    collapsedSet.clear();
  }

  /**
   * @return A unmodifiable set of paths of the expanded nodes.
   */
  public Set<TreePath> getExpandedSet() {
    return Collections.unmodifiableSet(expandedSet);
  }

  /**
   * @return A unmodifiable set of paths of the collapsed nodes.
   */
  public Set<TreePath> getCollapsedSet() {
    return Collections.unmodifiableSet(collapsedSet);
  }
}
