/*
   * (non-Javadoc)
   *
   * @see
   * com.cohesiva.drifter.datastruct.IComplex#onMerge(com.cohesiva.drifter
   * .common.Location, com.cohesiva.drifter.datastruct.IComplex)
   */
  @Override
  public void onMerge(ISplitContext ctx, IComplex mergedWhole) {
    SquareWithCircles wholeComplex = ((SquareWithCircles) mergedWhole);

    // {{ give the circles back to merged whole
    for (Iterator<Circle> iter = this.circles.iterator(); iter.hasNext(); ) {
      Circle circle = iter.next();
      int originDepth = CirclePopulationStrategy.originDepth(circle);

      if (originDepth <= wholeComplex.depth()) {
        wholeComplex.circles.add(circle);
        iter.remove();
      }
    }

    this.circles.clear();
    // }}

    // reset random
    wholeComplex.random = new Random(ctx.index());

    this.square = null;
    this.random = null;
    this.circles = null;
  }
  @Override
  public void populate(SquareWithCircles square, Location referenceLocation) {
    // set up fuse
    int idx = square.depth() <= 6 ? square.depth() : 6;
    Location topLeft = square.square.getTopLeft();

    // {{ compute min and max coords
    int minx = (int) topLeft.x();
    int miny = (int) topLeft.y() - square.square.getWidth() + CIRCE_RADIUS_BY_DEPTH[idx];
    int maxx = (int) topLeft.x() + square.square.getWidth() - CIRCE_RADIUS_BY_DEPTH[idx];
    int maxy = (int) topLeft.y();
    // }}

    // {{ compute location bounds
    Location minLocation = new Location(minx, miny, 0, DistanceUnit.LIGHT_YEAR);
    Location maxLocation = new Location(maxx, maxy, 0, DistanceUnit.LIGHT_YEAR);
    // }}

    // populate 1 new circle per square
    // square.circles.add(new Circle(minLocation, CIRCE_RADIUS_BY_DEPTH[idx]));
    // square.circles.add(new Circle(maxLocation, CIRCE_RADIUS_BY_DEPTH[idx]));
    Location randomLocation = new RandomLocation(minLocation, maxLocation, square.random);
    square.circles.add(new Circle(randomLocation, CIRCE_RADIUS_BY_DEPTH[idx]));
    /*for (int count = 1; count <= 1; count++) {
    	Location randomLocation = new RandomLocation(minLocation,
    			maxLocation, square.random);
    	square.circles.add(new Circle(randomLocation,
    			CIRCE_RADIUS_BY_DEPTH[idx]));
    }*/
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * com.cohesiva.drifter.datastruct.IComplex#onSplitComplete(com.cohesiva
   * .drifter.common.Location, com.cohesiva.drifter.datastruct.IComplex[])
   */
  @Override
  public void onSplitComplete(ISplitContext ctx, IComplex[] splittedParts) {
    // {{ distribute all circles to splitted complexes
    for (Iterator<Circle> iter = this.circles.iterator(); iter.hasNext(); ) {
      Circle circle = iter.next();

      for (IOffset offset : this.splitDegree().offsets()) {
        SquareWithCircles holder = (SquareWithCircles) splittedParts[offset.offsetIndex()];
        if (holder.isSurrounding(ctx.referenceLocation(), 0)) {
          holder.circles.add(circle);
          iter.remove();

          break;
        }
      }
    }
    // }}
  }