import y.base.Graph;
import y.base.Node;
import y.layout.NodeLayout;
import y.util.DataProviderAdapter;
import y.view.Graph2D;
import y.view.NodeRealizer;

/**
 * DataProvider implementation that provides for each node a
 * {@link demo.view.layout.ContainsTest} instance that calculates an inclusion
 * test result using the corresponding {@link NodeRealizer}'s
 * {@link NodeRealizer#contains(double, double)} implementation.
 * <br>
 * Note that this DataProvider returns the same instance for every element
 * queried for but reconfigures that instance to calculate results for the
 * correct node.
 * <p>
 * <b>Important:</b><br>
 * To ensure correct results, this DataProvider may only be associated to
 * {@link y.view.Graph2D} instances.
 * </p>
 * @see demo.view.layout.ContainsTest
 * @see demo.view.layout.ContainsTest#CONTAINS_TEST_DPKEY
 *
 * @author Thomas Behr
 */
public class NodeRealizerContainsTest extends DataProviderAdapter {
  private final ThisContainsTest ic;

  public NodeRealizerContainsTest() {
    this.ic = new ThisContainsTest();
  }

  public Object get( final Object dataHolder ) {
    if (!(dataHolder instanceof Node)) {
      return null;
    }
    ic.node = (Node) dataHolder;
    return ic;
  }

  private static final class ThisContainsTest implements ContainsTest {
    Node node;

    public boolean contains( NodeLayout nl, double x, double y ) {
      final Graph g = node.getGraph();
      if (!(g instanceof Graph2D)) {
        // might be improved by testing the given NodeLayout bounding box
        return false;
      }

      // might be improved by reusing previously created copies
      final NodeRealizer nr = ((Graph2D) g).getRealizer(node).createCopy();
      nr.setFrame(nl.getX(), nl.getY(), nl.getWidth(), nl.getHeight());
      return nr.contains(x, y);
    }
  }
}
