package org.apache.samoa.streams.clustering;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2014 - 2015 Apache Software Foundation
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Random;
import java.util.Vector;

import org.apache.samoa.instances.Attribute;
import org.apache.samoa.instances.DenseInstance;
import org.apache.samoa.instances.Instance;
import org.apache.samoa.instances.Instances;
import org.apache.samoa.instances.InstancesHeader;
import org.apache.samoa.moa.cluster.Clustering;
import org.apache.samoa.moa.cluster.SphereCluster;
import org.apache.samoa.moa.core.AutoExpandVector;
import org.apache.samoa.moa.core.DataPoint;
import org.apache.samoa.moa.core.InstanceExample;
import org.apache.samoa.moa.core.ObjectRepository;
import org.apache.samoa.moa.tasks.TaskMonitor;
import org.apache.samoa.streams.InstanceStream;

import com.github.javacliparser.FlagOption;
import com.github.javacliparser.FloatOption;
import com.github.javacliparser.IntOption;

public class RandomRBFGeneratorEvents extends ClusteringStream {
  private transient Vector<ClusterEventListener> listeners;

  private static final long serialVersionUID = 1L;

  public IntOption modelRandomSeedOption = new IntOption("modelRandomSeed",
      'm', "Seed for random generation of model.", 1);

  public IntOption instanceRandomSeedOption = new IntOption(
      "instanceRandomSeed", 'i',
      "Seed for random generation of instances.", 5);

  public IntOption numClusterOption = new IntOption("numCluster", 'K',
      "The average number of centroids in the model.", 5, 1, Integer.MAX_VALUE);

  public IntOption numClusterRangeOption = new IntOption("numClusterRange", 'k',
      "Deviation of the number of centroids in the model.", 3, 0, Integer.MAX_VALUE);

  public FloatOption kernelRadiiOption = new FloatOption("kernelRadius", 'R',
      "The average radii of the centroids in the model.", 0.07, 0, 1);

  public FloatOption kernelRadiiRangeOption = new FloatOption("kernelRadiusRange", 'r',
      "Deviation of average radii of the centroids in the model.", 0, 0, 1);

  public FloatOption densityRangeOption = new FloatOption("densityRange", 'd',
      "Offset of the average weight a cluster has. Value of 0 means all cluster " +
          "contain the same amount of points.", 0, 0, 1);

  public IntOption speedOption = new IntOption("speed", 'V',
      "Kernels move a predefined distance of 0.01 every X points", 500, 1, Integer.MAX_VALUE);

  public IntOption speedRangeOption = new IntOption("speedRange", 'v',
      "Speed/Velocity point offset", 0, 0, Integer.MAX_VALUE);

  public FloatOption noiseLevelOption = new FloatOption("noiseLevel", 'N',
      "Noise level", 0.1, 0, 1);

  public FlagOption noiseInClusterOption = new FlagOption("noiseInCluster", 'n',
      "Allow noise to be placed within a cluster");

  public IntOption eventFrequencyOption = new IntOption("eventFrequency", 'E',
      "Event frequency. Enable at least one of the events below and set numClusterRange!", 30000, 0, Integer.MAX_VALUE);

  public FlagOption eventMergeSplitOption = new FlagOption("eventMergeSplitOption", 'M',
      "Enable merging and splitting of clusters. Set eventFrequency and numClusterRange!");

  public FlagOption eventDeleteCreateOption = new FlagOption("eventDeleteCreate", 'C',
      "Enable emering and disapperaing of clusters. Set eventFrequency and numClusterRange!");

  private double merge_threshold = 0.7;
  private int kernelMovePointFrequency = 10;
  private double maxDistanceMoveThresholdByStep = 0.01;
  private int maxOverlapFitRuns = 50;
  private double eventFrequencyRange = 0;

  private boolean debug = false;

  private AutoExpandVector<GeneratorCluster> kernels;
  protected Random instanceRandom;
  protected InstancesHeader streamHeader;
  private int numGeneratedInstances;
  private int numActiveKernels;
  private int nextEventCounter;
  private int nextEventChoice = -1;
  private int clusterIdCounter;
  private GeneratorCluster mergeClusterA;
  private GeneratorCluster mergeClusterB;
  private boolean mergeKernelsOverlapping = false;

  private class GeneratorCluster implements Serializable {
    // TODO: points is redundant to microclusterpoints, we need to come
    // up with a good strategy that microclusters get updated and
    // rebuild if needed. Idea: Sort microclusterpoints by timestamp and let
    // microclusterdecay hold the timestamp for when the last point in a
    // microcluster gets kicked, then we rebuild... or maybe not... could be
    // same as searching for point to be kicked. more likely is we rebuild
    // fewer times then insert.

    private static final long serialVersionUID = -6301649898961112942L;

    SphereCluster generator;
    int kill = -1;
    boolean merging = false;
    double[] moveVector;
    int totalMovementSteps;
    int currentMovementSteps;
    boolean isSplitting = false;

    LinkedList<DataPoint> points = new LinkedList<>();
    ArrayList<SphereCluster> microClusters = new ArrayList<>();
    ArrayList<ArrayList<DataPoint>> microClustersPoints = new ArrayList<>();
    ArrayList<Integer> microClustersDecay = new ArrayList<>();

    public GeneratorCluster(int label) {
      boolean outofbounds = true;
      int tryCounter = 0;
      while (outofbounds && tryCounter < maxOverlapFitRuns) {
        tryCounter++;
        outofbounds = false;
        double[] center = new double[numAttsOption.getValue()];
        double radius = kernelRadiiOption.getValue() + (instanceRandom.nextBoolean() ? -1 : 1)
            * kernelRadiiRangeOption.getValue() * instanceRandom.nextDouble();
        while (radius <= 0) {
          radius = kernelRadiiOption.getValue() + (instanceRandom.nextBoolean() ? -1 : 1)
              * kernelRadiiRangeOption.getValue() * instanceRandom.nextDouble();
        }
        for (int j = 0; j < numAttsOption.getValue(); j++) {
          center[j] = instanceRandom.nextDouble();
          if (center[j] - radius < 0 || center[j] + radius > 1) {
            outofbounds = true;
            break;
          }
        }
        generator = new SphereCluster(center, radius);
      }
      if (tryCounter < maxOverlapFitRuns) {
        generator.setId(label);
        double avgWeight = 1.0 / numClusterOption.getValue();
        double weight = avgWeight + (instanceRandom.nextBoolean() ? -1 : 1) * avgWeight * densityRangeOption.getValue()
            * instanceRandom.nextDouble();
        generator.setWeight(weight);
        setDesitnation(null);
      }
      else {
        generator = null;
        kill = 0;
        System.out.println("Tried " + maxOverlapFitRuns + " times to create kernel. Reduce average radii.");
      }
    }

    public GeneratorCluster(int label, SphereCluster cluster) {
      this.generator = cluster;
      cluster.setId(label);
      setDesitnation(null);
    }

    public int getWorkID() {
      for (int c = 0; c < kernels.size(); c++) {
        if (kernels.get(c).equals(this))
          return c;
      }
      return -1;
    }

    private void updateKernel() {
      if (kill == 0) {
        kernels.remove(this);
      }
      if (kill > 0) {
        kill--;
      }
      // we could be lot more precise if we would keep track of timestamps of
      // points
      // then we could remove all old points and rebuild the cluster on up to
      // date point base
      // BUT worse the effort??? so far we just want to avoid overlap with this,
      // so its more
      // konservative as needed. Only needs to change when we need a thighter
      // representation
      for (int m = 0; m < microClusters.size(); m++) {
        if (numGeneratedInstances - microClustersDecay.get(m) > decayHorizonOption.getValue()) {
          microClusters.remove(m);
          microClustersPoints.remove(m);
          microClustersDecay.remove(m);
        }
      }

      if (!points.isEmpty()
          && numGeneratedInstances - points.getFirst().getTimestamp() >= decayHorizonOption.getValue()) {
        // if(debug)
        // System.out.println("Cleaning up macro cluster "+generator.getId());
        points.removeFirst();
      }

    }

    private void addInstance(Instance instance) {
      DataPoint point = new DataPoint(instance, numGeneratedInstances);
      points.add(point);

      int minMicroIndex = -1;
      double minHullDist = Double.MAX_VALUE;
      boolean inserted = false;
      // we favour more recently build clusters so we can remove earlier cluster sooner
      for (int m = microClusters.size() - 1; m >= 0; m--) {
        SphereCluster micro = microClusters.get(m);
        double hulldist = micro.getCenterDistance(point) - micro.getRadius();
        // point fits into existing cluster
        if (hulldist <= 0) {
          microClustersPoints.get(m).add(point);
          microClustersDecay.set(m, numGeneratedInstances);
          inserted = true;
          break;
        }
        // if not, check if its at least the closest cluster
        else {
          if (hulldist < minHullDist) {
            minMicroIndex = m;
            minHullDist = hulldist;
          }
        }
      }
      // Reseting index choice for alternative cluster building
      if (!inserted) {
        // add to closest cluster and expand cluster
        // minMicroIndex might have been reset above
        // create new micro cluster
        ArrayList<DataPoint> microPoints = new ArrayList<>();
        microPoints.add(point);
        SphereCluster s;
        s = new SphereCluster(generator.getCenter(), generator.getRadius(), 1);

        microClusters.add(s);
        microClustersPoints.add(microPoints);
        microClustersDecay.add(numGeneratedInstances);
        int id = 0;
        while (id < kernels.size()) {
          if (kernels.get(id) == this)
            break;
          id++;
        }
        s.setGroundTruth(id);
      }

    }

    private void move() {
      if (currentMovementSteps < totalMovementSteps) {
        currentMovementSteps++;
        if (moveVector != null) {
          double[] center = generator.getCenter();
          boolean outofbounds = true;
          while (outofbounds) {
            double radius = generator.getRadius();
            outofbounds = false;
            center = generator.getCenter();
            for (int d = 0; d < center.length; d++) {
              center[d] += moveVector[d];
              if (center[d] - radius < 0 || center[d] + radius > 1) {
                outofbounds = true;
                setDesitnation(null);
                break;
              }
            }
          }
          generator.setCenter(center);
        }
      }
      else {
        if (!merging) {
          setDesitnation(null);
          isSplitting = false;
        }
      }
    }

    void setDesitnation(double[] destination) {

      if (destination == null) {
        destination = new double[numAttsOption.getValue()];
        for (int j = 0; j < numAttsOption.getValue(); j++) {
          destination[j] = instanceRandom.nextDouble();
        }
      }
      double[] center = generator.getCenter();
      int dim = center.length;

      double[] v = new double[dim];

      for (int d = 0; d < dim; d++) {
        v[d] = destination[d] - center[d];
      }
      setMoveVector(v);
    }

    void setMoveVector(double[] vector) {
      // we are ignoring the steps, otherwise we have to change
      // speed of the kernels, do we want that?
      moveVector = vector;
      int speedInPoints = speedOption.getValue();
      if (speedRangeOption.getValue() > 0)
        speedInPoints += (instanceRandom.nextBoolean() ? -1 : 1) * instanceRandom.nextInt(speedRangeOption.getValue());
      if (speedInPoints < 1)
        speedInPoints = speedOption.getValue();

      double length = 0;
      for (int d = 0; d < moveVector.length; d++) {
        length += Math.pow(vector[d], 2);
      }
      length = Math.sqrt(length);

      totalMovementSteps = (int) (length / (maxDistanceMoveThresholdByStep * kernelMovePointFrequency) * speedInPoints);
      for (int d = 0; d < moveVector.length; d++) {
        moveVector[d] /= (double) totalMovementSteps;
      }

      currentMovementSteps = 0;
      // if(debug){
      // System.out.println("Setting new direction for C"+generator.getId()+": distance "
      // +length+" in "+totalMovementSteps+" steps");
      // }
    }

    private String tryMerging(GeneratorCluster merge) {
      String message = "";
      double overlapDegree = generator.overlapRadiusDegree(merge.generator);
      if (overlapDegree > merge_threshold) {
        SphereCluster mcluster = merge.generator;
        double radius = Math.max(generator.getRadius(), mcluster.getRadius());
        generator.combine(mcluster);

        // //adjust radius, get bigger and bigger with high dim data
        generator.setRadius(radius);
        // double[] center = generator.getCenter();
        // double[] mcenter = mcluster.getCenter();
        // double weight = generator.getWeight();
        // double mweight = generator.getWeight();
        // // for (int i = 0; i < center.length; i++) {
        // // center[i] = (center[i] * weight + mcenter[i] * mweight) / (mweight
        // + weight);
        // // }
        // generator.setWeight(weight + mweight);
        message = "Clusters merging: " + mergeClusterB.generator.getId() + " into " + mergeClusterA.generator.getId();

        // clean up and restet merging stuff
        // mark kernel so it gets killed when it doesn't contain any more
        // instances
        merge.kill = decayHorizonOption.getValue();
        // set weight to 0 so no new instances will be created in the cluster
        mcluster.setWeight(0.0);
        normalizeWeights();
        numActiveKernels--;
        mergeClusterB = mergeClusterA = null;
        merging = false;
        mergeKernelsOverlapping = false;
      }
      else {
        if (overlapDegree > 0 && !mergeKernelsOverlapping) {
          mergeKernelsOverlapping = true;
          message = "Merge overlapping started";
        }
      }
      return message;
    }

    private String splitKernel() {
      isSplitting = true;
      // todo radius range
      double radius = kernelRadiiOption.getValue();
      double avgWeight = 1.0 / numClusterOption.getValue();
      double weight = avgWeight + avgWeight * densityRangeOption.getValue() * instanceRandom.nextDouble();
      SphereCluster spcluster;

      double[] center = generator.getCenter();
      spcluster = new SphereCluster(center, radius, weight);

      GeneratorCluster gc = new GeneratorCluster(clusterIdCounter++, spcluster);
      gc.isSplitting = true;
      kernels.add(gc);
      normalizeWeights();
      numActiveKernels++;
      return "Split from Kernel " + generator.getId();
    }

    private String fadeOut() {
      kill = decayHorizonOption.getValue();
      generator.setWeight(0.0);
      numActiveKernels--;
      normalizeWeights();
      return "Fading out C" + generator.getId();
    }

  }

  public RandomRBFGeneratorEvents() {
    noiseInClusterOption.set();
    // eventDeleteCreateOption.set();
    // eventMergeSplitOption.set();
  }

  public InstancesHeader getHeader() {
    return streamHeader;
  }

  public long estimatedRemainingInstances() {
    return -1;
  }

  public boolean hasMoreInstances() {
    return true;
  }

  public boolean isRestartable() {
    return true;
  }

  @Override
  public void prepareForUseImpl(TaskMonitor monitor, ObjectRepository repository) {
    monitor.setCurrentActivity("Preparing random RBF...", -1.0);
    generateHeader();
    restart();
  }

  public void restart() {
    instanceRandom = new Random(instanceRandomSeedOption.getValue());
    nextEventCounter = eventFrequencyOption.getValue();
    nextEventChoice = getNextEvent();
    numActiveKernels = 0;
    numGeneratedInstances = 0;
    clusterIdCounter = 0;
    mergeClusterA = mergeClusterB = null;
    kernels = new AutoExpandVector<>();

    initKernels();
  }

  protected void generateHeader() { // 2013/06/02: Noise label
    ArrayList<Attribute> attributes = new ArrayList<>();
    for (int i = 0; i < this.numAttsOption.getValue(); i++) {
      attributes.add(new Attribute("att" + (i + 1)));
    }

    ArrayList<String> classLabels = new ArrayList<>();
    for (int i = 0; i < this.numClusterOption.getValue(); i++) {
      classLabels.add("class" + (i + 1));
    }
    if (noiseLevelOption.getValue() > 0)
      classLabels.add("noise"); // The last label = "noise"

    attributes.add(new Attribute("class", classLabels));
    streamHeader = new InstancesHeader(new Instances(getCLICreationString(InstanceStream.class), attributes, 0));
    streamHeader.setClassIndex(streamHeader.numAttributes() - 1);
  }

  protected void initKernels() {
    for (int i = 0; i < numClusterOption.getValue(); i++) {
      kernels.add(new GeneratorCluster(clusterIdCounter));
      numActiveKernels++;
      clusterIdCounter++;
    }
    normalizeWeights();
  }

  public InstanceExample nextInstance() {
    numGeneratedInstances++;
    eventScheduler();

    // make room for the classlabel
    double[] values_new = new double[numAttsOption.getValue()]; // +1
    double[] values;
    int clusterChoice = -1;

    if (instanceRandom.nextDouble() > noiseLevelOption.getValue()) {
      clusterChoice = chooseWeightedElement();
      values = kernels.get(clusterChoice).generator.sample(instanceRandom).toDoubleArray();
    }
    else {
      // get random noise point
      values = getNoisePoint();
    }

    if (Double.isNaN(values[0])) {
      System.out.println("Instance corrupted:" + numGeneratedInstances);
    }
    System.arraycopy(values, 0, values_new, 0, values.length);

    Instance inst = new DenseInstance(1.0, values_new);
    inst.setDataset(getHeader());
    if (clusterChoice == -1) {
      // 2013/06/02 (Yunsu Kim)
      // Noise instance has the last class value instead of "-1"
      // Preventing ArrayIndexOutOfBoundsException in WriteStreamToARFFFile
      inst.setClassValue(numClusterOption.getValue());
    }
    else {
      inst.setClassValue(kernels.get(clusterChoice).generator.getId());
      // Do we need micro cluster representation if have overlapping clusters?
      // if(!overlappingOption.isSet())
      kernels.get(clusterChoice).addInstance(inst);
    }
    // System.out.println(numGeneratedInstances+": Overlap is"+updateOverlaps());

    return new InstanceExample(inst);
  }

  public Clustering getGeneratingClusters() {
    Clustering clustering = new Clustering();
    for (GeneratorCluster kernel : kernels) {
      clustering.add(kernel.generator);
    }
    return clustering;
  }

  public Clustering getMicroClustering() {
    Clustering clustering = new Clustering();
    int id = 0;

    for (GeneratorCluster kernel : kernels) {
      for (int m = 0; m < kernel.microClusters.size(); m++) {
        kernel.microClusters.get(m).setId(id);
        kernel.microClusters.get(m).setGroundTruth(kernel.generator.getId());
        clustering.add(kernel.microClusters.get(m));
        id++;
      }
    }

    // System.out.println("numMicroKernels "+clustering.size());
    return clustering;
  }

  /**************************** EVENTS ******************************************/
  private void eventScheduler() {

    for (GeneratorCluster kernel : kernels) {
      kernel.updateKernel();
    }

    nextEventCounter--;
    // only move kernels every 10 points, performance reasons????
    // should this be randomized as well???
    if (nextEventCounter % kernelMovePointFrequency == 0) {
      // move kernels
      for (GeneratorCluster kernel : kernels) {
        kernel.move();
        // overlapControl();
      }
    }

    if (eventFrequencyOption.getValue() == 0) {
      return;
    }

    String type = "";
    String message = "";
    boolean eventFinished = false;
    switch (nextEventChoice) {
    case 0:
      if (numActiveKernels > 1 && numActiveKernels > numClusterOption.getValue() - numClusterRangeOption.getValue()) {
        message = mergeKernels(nextEventCounter);
        type = "Merge";
      }
      if (mergeClusterA == null && mergeClusterB == null && message.startsWith("Clusters merging")) {
        eventFinished = true;
      }
      break;
    case 1:
      if (nextEventCounter <= 0) {
        if (numActiveKernels < numClusterOption.getValue() + numClusterRangeOption.getValue()) {
          type = "Split";
          message = splitKernel();
        }
        eventFinished = true;
      }
      break;
    case 2:
      if (nextEventCounter <= 0) {
        if (numActiveKernels > 1 && numActiveKernels > numClusterOption.getValue() - numClusterRangeOption.getValue()) {
          message = fadeOut();
          type = "Delete";
        }
        eventFinished = true;
      }
      break;
    case 3:
      if (nextEventCounter <= 0) {
        if (numActiveKernels < numClusterOption.getValue() + numClusterRangeOption.getValue()) {
          message = fadeIn();
          type = "Create";
        }
        eventFinished = true;
      }
      break;

    }
    if (eventFinished) {
      nextEventCounter = (int) (eventFrequencyOption.getValue() + (instanceRandom.nextBoolean() ? -1 : 1)
          * eventFrequencyOption.getValue() * eventFrequencyRange * instanceRandom.nextDouble());
      nextEventChoice = getNextEvent();
      // System.out.println("Next event choice: "+nextEventChoice);
    }
    if (!message.isEmpty()) {
      message += " (numKernels = " + numActiveKernels + " at " + numGeneratedInstances + ")";
      if (!type.equals("Merge") || message.startsWith("Clusters merging"))
        fireClusterChange(numGeneratedInstances, type, message);
    }
  }

  private int getNextEvent() {
    int choice = -1;
    boolean lowerLimit = numActiveKernels <= numClusterOption.getValue() - numClusterRangeOption.getValue();
    boolean upperLimit = numActiveKernels >= numClusterOption.getValue() + numClusterRangeOption.getValue();

    if (!lowerLimit || !upperLimit) {
      int mode = -1;
      if (eventDeleteCreateOption.isSet() && eventMergeSplitOption.isSet()) {
        mode = instanceRandom.nextInt(2);
      }

      if (mode == 0 || (mode == -1 && eventMergeSplitOption.isSet())) {
        // have we reached a limit? if not free choice
        if (!lowerLimit && !upperLimit)
          choice = instanceRandom.nextInt(2);
        else
        // we have a limit. if lower limit, choose split
        if (lowerLimit)
          choice = 1;
        // otherwise we reached upper level, choose merge
        else
          choice = 0;
      }

      if (mode == 1 || (mode == -1 && eventDeleteCreateOption.isSet())) {
        // have we reached a limit? if not free choice
        if (!lowerLimit && !upperLimit)
          choice = instanceRandom.nextInt(2) + 2;
        else
        // we have a limit. if lower limit, choose create
        if (lowerLimit)
          choice = 3;
        // otherwise we reached upper level, choose delete
        else
          choice = 2;
      }
    }

    return choice;
  }

  private String fadeOut() {
    int id = instanceRandom.nextInt(kernels.size());
    while (kernels.get(id).kill != -1)
      id = instanceRandom.nextInt(kernels.size());

    return kernels.get(id).fadeOut();
  }

  private String fadeIn() {
    GeneratorCluster gc = new GeneratorCluster(clusterIdCounter++);
    kernels.add(gc);
    numActiveKernels++;
    normalizeWeights();
    return "Creating new cluster";
  }

  private String changeWeight(boolean increase) {
    double changeRate = 0.1;
    int id = instanceRandom.nextInt(kernels.size());
    while (kernels.get(id).kill != -1)
      id = instanceRandom.nextInt(kernels.size());

    int sign = 1;
    if (!increase)
      sign = -1;
    double weight_old = kernels.get(id).generator.getWeight();
    double delta = sign * numActiveKernels * instanceRandom.nextDouble() * changeRate;
    kernels.get(id).generator.setWeight(weight_old + delta);

    normalizeWeights();

    String message;
    if (increase)
      message = "Increase ";
    else
      message = "Decrease ";
    message += " weight on Cluster " + id + " from " + weight_old + " to " + (weight_old + delta);
    return message;

  }

  private String changeRadius(boolean increase) {
    double maxChangeRate = 0.1;
    int id = instanceRandom.nextInt(kernels.size());
    while (kernels.get(id).kill != -1)
      id = instanceRandom.nextInt(kernels.size());

    int sign = 1;
    if (!increase)
      sign = -1;

    double r_old = kernels.get(id).generator.getRadius();
    double r_new = r_old + sign * r_old * instanceRandom.nextDouble() * maxChangeRate;
    if (r_new >= 0.5)
      return "Radius to big";
    kernels.get(id).generator.setRadius(r_new);

    String message;
    if (increase)
      message = "Increase ";
    else
      message = "Decrease ";
    message += " radius on Cluster " + id + " from " + r_old + " to " + r_new;
    return message;
  }

  private String splitKernel() {
    int id = instanceRandom.nextInt(kernels.size());
    while (kernels.get(id).kill != -1)
      id = instanceRandom.nextInt(kernels.size());

    return kernels.get(id).splitKernel();
  }

  private String mergeKernels(int steps) {
    if (numActiveKernels > 1 && ((mergeClusterA == null && mergeClusterB == null))) {

      // choose clusters to merge
      double diseredDist = steps / speedOption.getValue() * maxDistanceMoveThresholdByStep;
      double minDist = Double.MAX_VALUE;
      // System.out.println("DisredDist:"+(2*diseredDist));
      for (int i = 0; i < kernels.size(); i++) {
        for (int j = 0; j < i; j++) {
          if (kernels.get(i).kill == -1 && kernels.get(j).kill == -1) {
            double kernelDist = kernels.get(i).generator.getCenterDistance(kernels.get(j).generator);
            double d = kernelDist - 2 * diseredDist;
            // System.out.println("Dist:"+i+" / "+j+" "+d);
            if (Math.abs(d) < minDist &&
                (minDist != Double.MAX_VALUE || d > 0 || Math.abs(d) < 0.001)) {
              minDist = Math.abs(d);
              mergeClusterA = kernels.get(i);
              mergeClusterB = kernels.get(j);
            }
          }
        }
      }

      if (mergeClusterA != null && mergeClusterB != null) {
        double[] merge_point = mergeClusterA.generator.getCenter();
        double[] v = mergeClusterA.generator.getDistanceVector(mergeClusterB.generator);
        for (int i = 0; i < v.length; i++) {
          merge_point[i] = merge_point[i] + v[i] * 0.5;
        }

        mergeClusterA.merging = true;
        mergeClusterB.merging = true;
        mergeClusterA.setDesitnation(merge_point);
        mergeClusterB.setDesitnation(merge_point);

        if (debug) {
          System.out.println("Center1" + Arrays.toString(mergeClusterA.generator.getCenter()));
          System.out.println("Center2" + Arrays.toString(mergeClusterB.generator.getCenter()));
          System.out.println("Vector" + Arrays.toString(v));

          System.out.println("Try to merge cluster " + mergeClusterA.generator.getId() +
              " into " + mergeClusterB.generator.getId() +
              " at " + Arrays.toString(merge_point) +
              " time " + numGeneratedInstances);
        }
        return "Init merge";
      }
    }

    if (mergeClusterA != null && mergeClusterB != null) {

      // movekernels will move the kernels close to each other,
      // we just need to check and merge here if they are close enough
      return mergeClusterA.tryMerging(mergeClusterB);
    }

    return "";
  }

  /************************* TOOLS **************************************/

  public void getDescription(StringBuilder sb, int indent) {

  }

  private double[] getNoisePoint() {
    double[] sample = new double[numAttsOption.getValue()];
    boolean incluster = true;
    int counter = 20;
    while (incluster) {
      for (int j = 0; j < numAttsOption.getValue(); j++) {
        sample[j] = instanceRandom.nextDouble();
      }
      incluster = false;
      if (!noiseInClusterOption.isSet() && counter > 0) {
        counter--;
        for (GeneratorCluster kernel : kernels) {
          for (int m = 0; m < kernel.microClusters.size(); m++) {
            Instance inst = new DenseInstance(1, sample);
            if (kernel.microClusters.get(m).getInclusionProbability(inst) > 0) {
              incluster = true;
              break;
            }
          }
          if (incluster)
            break;
        }
      }
    }

    // double [] sample = new double [numAttsOption.getValue()];
    // for (int j = 0; j < numAttsOption.getValue(); j++) {
    // sample[j] = instanceRandom.nextDouble();
    // }

    return sample;
  }

  private int chooseWeightedElement() {
    double r = instanceRandom.nextDouble();

    // Determine index of choosen element
    int i = 0;
    while (r > 0.0) {
      r -= kernels.get(i).generator.getWeight();
      i++;
    }
    --i; // Overcounted once
    // System.out.println(i);
    return i;
  }

  private void normalizeWeights() {
    double sumWeights = 0.0;
    for (GeneratorCluster kernel : kernels) {
      sumWeights += kernel.generator.getWeight();
    }
    for (GeneratorCluster kernel : kernels) {
      kernel.generator.setWeight(kernel.generator.getWeight() / sumWeights);
    }
  }

  /*************** EVENT Listener *********************/
  // should go into the superclass of the generator, create new one for cluster
  // streams?

  /** Add a listener */
  synchronized public void addClusterChangeListener(ClusterEventListener l) {
    if (listeners == null)
      listeners = new Vector<>();
    listeners.addElement(l);
  }

  /** Remove a listener */
  synchronized public void removeClusterChangeListener(ClusterEventListener l) {
    if (listeners == null)
      listeners = new Vector<>();
    listeners.removeElement(l);
  }

  /** Fire a ClusterChangeEvent to all registered listeners */
  protected void fireClusterChange(long timestamp, String type, String message) {
    // if we have no listeners, do nothing...
    if (listeners != null && !listeners.isEmpty()) {
      // create the event object to send
      ClusterEvent event =
          new ClusterEvent(this, timestamp, type, message);

      // make a copy of the listener list in case
      // anyone adds/removes listeners
      Vector<ClusterEventListener> targets;
      synchronized (this) {
        targets = (Vector<ClusterEventListener>) listeners.clone();
      }

      // walk through the listener list and
      // call the sunMoved method in each
      Enumeration e = targets.elements();
      while (e.hasMoreElements()) {
        ClusterEventListener l = (ClusterEventListener) e.nextElement();
        l.changeCluster(event);

      }
    }
  }

  @Override
  public String getPurposeString() {
    return "Generates a random radial basis function stream.";
  }

  public String getParameterString() {
    return "";
  }

}
