package org.apache.samoa.moa.clusterers;

/*
 * #%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.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

import org.apache.samoa.instances.Instance;
import org.apache.samoa.moa.cluster.Clustering;
import org.apache.samoa.moa.cluster.SphereCluster;
import org.apache.samoa.moa.core.DataPoint;
import org.apache.samoa.moa.core.Measurement;

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

public class ClusterGenerator extends AbstractClusterer {

  private static final long serialVersionUID = 1L;

  public IntOption timeWindowOption = new IntOption("timeWindow",
      't', "Rang of the window.", 1000);

  public FloatOption radiusDecreaseOption = new FloatOption("radiusDecrease", 'r',
      "The average radii of the centroids in the model.", 0, 0, 1);

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

  public FloatOption positionOffsetOption = new FloatOption("positionOffset", 'p',
      "The average radii of the centroids in the model.", 0, 0, 1);

  public FloatOption clusterRemoveOption = new FloatOption("clusterRemove", 'D',
      "Deletes complete clusters from the clustering.", 0, 0, 1);

  public FloatOption joinClustersOption = new FloatOption("joinClusters", 'j',
      "Join two clusters if their hull distance is less minRadius times this factor.", 0, 0, 1);

  public FloatOption clusterAddOption = new FloatOption("clusterAdd", 'A',
      "Adds additional clusters.", 0, 0, 1);

  private ArrayList<DataPoint> points;
  private int instanceCounter;
  private int windowCounter;
  private Random random;
  private Clustering sourceClustering = null;

  @Override
  public void resetLearningImpl() {
    points = new ArrayList<>();
    instanceCounter = 0;
    windowCounter = 0;
    random = new Random(227);

    // joinClustersOption.set();
    // evaluateMicroClusteringOption.set();
  }

  @Override
  public void trainOnInstanceImpl(Instance inst) {
    if (windowCounter >= timeWindowOption.getValue()) {
      points.clear();
      windowCounter = 0;
    }
    windowCounter++;
    instanceCounter++;
    points.add(new DataPoint(inst, instanceCounter));
  }

  @Override
  public boolean implementsMicroClusterer() {
    return true;
  }

  public void setSourceClustering(Clustering source) {
    sourceClustering = source;
  }

  @Override
  public Clustering getMicroClusteringResult() {
    // System.out.println("Numcluster:"+clustering.size()+" / "+num);
    // Clustering source_clustering = new Clustering(points, overlapThreshold,
    // microInitMinPoints);
    if (sourceClustering == null) {

      System.out.println("You need to set a source clustering for the ClusterGenerator to work");
      return null;
    }
    return alterClustering(sourceClustering);
  }

  public Clustering getClusteringResult() {
    sourceClustering = new Clustering(points);
    // if(sourceClustering == null){
    // System.out.println("You need to set a source clustering for the ClusterGenerator to work");
    // return null;
    // }
    return alterClustering(sourceClustering);
  }

  private Clustering alterClustering(Clustering scclustering) {
    // percentage of the radius that will be cut off
    // 0: no changes to radius
    // 1: radius of 0
    double errLevelRadiusDecrease = radiusDecreaseOption.getValue();

    // 0: no changes to radius
    // 1: radius 100% bigger
    double errLevelRadiusIncrease = radiusIncreaseOption.getValue();

    // 0: no changes
    // 1: distance between centers is 2 * original radius
    double errLevelPosition = positionOffsetOption.getValue();

    int numRemoveCluster = (int) (clusterRemoveOption.getValue() * scclustering.size());

    int numAddCluster = (int) (clusterAddOption.getValue() * scclustering.size());

    for (int c = 0; c < numRemoveCluster; c++) {
      int delId = random.nextInt(scclustering.size());
      scclustering.remove(delId);
    }

    int numCluster = scclustering.size();
    double[] err_seeds = new double[numCluster];
    double err_seed_sum = 0.0;
    double tmp_seed;
    for (int i = 0; i < numCluster; i++) {
      tmp_seed = random.nextDouble();
      err_seeds[i] = err_seed_sum + tmp_seed;
      err_seed_sum += tmp_seed;
    }

    double sumWeight = 0;
    for (int i = 0; i < numCluster; i++) {
      sumWeight += scclustering.get(i).getWeight();
    }

    Clustering clustering = new Clustering();

    for (int i = 0; i < numCluster; i++) {
      if (!(scclustering.get(i) instanceof SphereCluster)) {
        System.out.println("Not a Sphere Cluster");
        continue;
      }
      SphereCluster sourceCluster = (SphereCluster) scclustering.get(i);
      double[] center = Arrays.copyOf(sourceCluster.getCenter(), sourceCluster.getCenter().length);
      double weight = sourceCluster.getWeight();
      double radius = sourceCluster.getRadius();

      // move cluster center
      double err_interval_width = 0.0;
      if (errLevelPosition > 0) {
        double errOffset = random.nextDouble() * err_interval_width / 2.0;
        double errOffsetDirection = ((random.nextBoolean()) ? 1 : -1);
        double level = errLevelPosition + errOffsetDirection * errOffset;
        double[] vector = new double[center.length];
        double vectorLength = 0;
        for (int d = 0; d < center.length; d++) {
          vector[d] = (random.nextBoolean() ? 1 : -1) * random.nextDouble();
          vectorLength += Math.pow(vector[d], 2);
        }
        vectorLength = Math.sqrt(vectorLength);

        // max is when clusters are next to each other
        double length = 2 * radius * level;

        for (int d = 0; d < center.length; d++) {
          // normalize length and then strecht to reach error position
          vector[d] = vector[d] / vectorLength * length;
        }
        // System.out.println("Center "+Arrays.toString(center));
        // System.out.println("Vector "+Arrays.toString(vector));
        // check if error position is within bounds
        double[] newCenter = new double[center.length];
        for (int d = 0; d < center.length; d++) {
          // check bounds, otherwise flip vector
          if (center[d] + vector[d] >= 0 && center[d] + vector[d] <= 1) {
            newCenter[d] = center[d] + vector[d];
          }
          else {
            newCenter[d] = center[d] + (-1) * vector[d];
          }
        }
        center = newCenter;
        for (int d = 0; d < center.length; d++) {
          if (newCenter[d] < 0 || newCenter[d] > 1) {
            System.out.println("This shouldnt have happend, Cluster center out of bounds:" + Arrays.toString(newCenter));
          }
        }
      }

      // alter radius
      if (errLevelRadiusDecrease > 0 || errLevelRadiusIncrease > 0) {
        double errOffset = random.nextDouble() * err_interval_width / 2.0;
        int errOffsetDirection = ((random.nextBoolean()) ? 1 : -1);

        if (errLevelRadiusDecrease > 0 && (errLevelRadiusIncrease == 0 || random.nextBoolean())) {
          double level = (errLevelRadiusDecrease + errOffsetDirection * errOffset);// *sourceCluster.getWeight()/sumWeight;
          level = (level < 0) ? 0 : level;
          level = (level > 1) ? 1 : level;
          radius *= (1 - level);
        }
        else {
          double level = errLevelRadiusIncrease + errOffsetDirection * errOffset;
          level = (level < 0) ? 0 : level;
          level = (level > 1) ? 1 : level;
          radius += radius * level;
        }
      }

      SphereCluster newCluster = new SphereCluster(center, radius, weight);
      newCluster.setMeasureValue("Source Cluster", "C" + sourceCluster.getId());

      clustering.add(newCluster);
    }

    if (joinClustersOption.getValue() > 0) {
      clustering = joinClusters(clustering);
    }

    // add new clusters by copying clusters and set a random center
    for (int c = 0; c < numAddCluster; c++) {
      int copyId = random.nextInt(clustering.size());
      SphereCluster scorg = (SphereCluster) clustering.get(copyId);
      int dim = scorg.getCenter().length;
      double[] center = new double[dim];
      double radius = scorg.getRadius();

      boolean outofbounds = true;
      int tryCounter = 0;
      while (outofbounds && tryCounter < 20) {
        tryCounter++;
        outofbounds = false;
        for (int j = 0; j < center.length; j++) {
          center[j] = random.nextDouble();
          if (center[j] - radius < 0 || center[j] + radius > 1) {
            outofbounds = true;
            break;
          }
        }
      }
      if (outofbounds) {
        System.out.println("Coludn't place additional cluster");
      }
      else {
        SphereCluster scnew = new SphereCluster(center, radius, scorg.getWeight() / 2);
        scorg.setWeight(scorg.getWeight() - scnew.getWeight());
        clustering.add(scnew);
      }
    }

    return clustering;

  }

  private Clustering joinClusters(Clustering clustering) {

    double radiusFactor = joinClustersOption.getValue();
    boolean[] merged = new boolean[clustering.size()];

    Clustering mclustering = new Clustering();

    if (radiusFactor > 0) {
      for (int c1 = 0; c1 < clustering.size(); c1++) {
        SphereCluster sc1 = (SphereCluster) clustering.get(c1);
        double minDist = Double.MAX_VALUE;
        int maxIndexCon = -1;
        for (int c2 = 0; c2 < clustering.size(); c2++) {
          SphereCluster sc2 = (SphereCluster) clustering.get(c2);
          // double over = sc1.overlapRadiusDegree(sc2);
          // if(over > 0 && over < minOver){
          // minOver = over;
          // maxindexOver = c2;
          // }
          double dist = sc1.getHullDistance(sc2);
          double threshold = Math.min(sc1.getRadius(), sc2.getRadius()) * radiusFactor;
          if (dist > 0 && dist < minDist && dist < threshold) {
            minDist = dist;
            maxIndexCon = c2;
          }
        }
        int maxindex;
        maxindex = maxIndexCon;

        if (maxindex != -1 && !merged[c1]) {
          merged[c1] = true;
          merged[maxindex] = true;
          SphereCluster scnew = new SphereCluster(sc1.getCenter(), sc1.getRadius(), sc1.getWeight());
          SphereCluster sc2 = (SphereCluster) clustering.get(maxindex);
          scnew.merge(sc2);
          mclustering.add(scnew);
        }
      }
    }

    for (int i = 0; i < merged.length; i++) {
      if (!merged[i])
        mclustering.add(clustering.get(i));
    }

    return mclustering;

  }

  @Override
  protected Measurement[] getModelMeasurementsImpl() {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public void getModelDescription(StringBuilder out, int indent) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public boolean isRandomizable() {
    return false;
  }

  @Override
  public boolean keepClassLabel() {
    return true;
  }

  public double[] getVotesForInstance(Instance inst) {
    return null;
  }
}
