package com.yahoo.labs.samoa.moa.streams.generators;

/*
 * #%L
 * SAMOA
 * %%
 *    Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
 * %%
 * 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 com.yahoo.labs.samoa.instances.Attribute;
import com.yahoo.labs.samoa.instances.DenseInstance;
import com.yahoo.labs.samoa.moa.core.FastVector;
import com.yahoo.labs.samoa.instances.Instance;
import com.yahoo.labs.samoa.instances.Instances;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Random;
import com.yahoo.labs.samoa.moa.core.InstanceExample;

import com.yahoo.labs.samoa.instances.InstancesHeader;
import com.yahoo.labs.samoa.moa.core.ObjectRepository;
import com.yahoo.labs.samoa.moa.options.AbstractOptionHandler;
import com.github.javacliparser.FloatOption;
import com.github.javacliparser.IntOption;
import com.yahoo.labs.samoa.moa.streams.InstanceStream;
import com.yahoo.labs.samoa.moa.tasks.TaskMonitor;

/**
 * Stream generator for a stream based on a randomly generated tree..
 * 
 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
 * @version $Revision: 7 $
 */
public class RandomTreeGenerator extends AbstractOptionHandler implements InstanceStream {

  @Override
  public String getPurposeString() {
    return "Generates a stream based on a randomly generated tree.";
  }

  private static final long serialVersionUID = 1L;

  public IntOption treeRandomSeedOption = new IntOption("treeRandomSeed",
      'r', "Seed for random generation of tree.", 1);

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

  public IntOption numClassesOption = new IntOption("numClasses", 'c',
      "The number of classes to generate.", 2, 2, Integer.MAX_VALUE);

  public IntOption numNominalsOption = new IntOption("numNominals", 'o',
      "The number of nominal attributes to generate.", 5, 0,
      Integer.MAX_VALUE);

  public IntOption numNumericsOption = new IntOption("numNumerics", 'u',
      "The number of numeric attributes to generate.", 5, 0,
      Integer.MAX_VALUE);

  public IntOption numValsPerNominalOption = new IntOption(
      "numValsPerNominal", 'v',
      "The number of values to generate per nominal attribute.", 5, 2,
      Integer.MAX_VALUE);

  public IntOption maxTreeDepthOption = new IntOption("maxTreeDepth", 'd',
      "The maximum depth of the tree concept.", 5, 0, Integer.MAX_VALUE);

  public IntOption firstLeafLevelOption = new IntOption(
      "firstLeafLevel",
      'l',
      "The first level of the tree above maxTreeDepth that can have leaves.",
      3, 0, Integer.MAX_VALUE);

  public FloatOption leafFractionOption = new FloatOption("leafFraction",
      'f',
      "The fraction of leaves per level from firstLeafLevel onwards.",
      0.15, 0.0, 1.0);

  protected static class Node implements Serializable {

    private static final long serialVersionUID = 1L;

    public int classLabel;

    public int splitAttIndex;

    public double splitAttValue;

    public Node[] children;
  }

  protected Node treeRoot;

  protected InstancesHeader streamHeader;

  protected Random instanceRandom;

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

  @Override
  public long estimatedRemainingInstances() {
    return -1;
  }

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

  @Override
  public void restart() {
    this.instanceRandom = new Random(this.instanceRandomSeedOption.getValue());
  }

  @Override
  public InstancesHeader getHeader() {
    return this.streamHeader;
  }

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

  @Override
  public InstanceExample nextInstance() {
    double[] attVals = new double[this.numNominalsOption.getValue()
        + this.numNumericsOption.getValue()];
    InstancesHeader header = getHeader();
    Instance inst = new DenseInstance(header.numAttributes());
    for (int i = 0; i < attVals.length; i++) {
      attVals[i] = i < this.numNominalsOption.getValue() ? this.instanceRandom.nextInt(this.numValsPerNominalOption
          .getValue())
          : this.instanceRandom.nextDouble();
      inst.setValue(i, attVals[i]);
    }
    inst.setDataset(header);
    inst.setClassValue(classifyInstance(this.treeRoot, attVals));
    return new InstanceExample(inst);
  }

  protected int classifyInstance(Node node, double[] attVals) {
    if (node.children == null) {
      return node.classLabel;
    }
    if (node.splitAttIndex < this.numNominalsOption.getValue()) {
      return classifyInstance(
          node.children[(int) attVals[node.splitAttIndex]], attVals);
    }
    return classifyInstance(
        node.children[attVals[node.splitAttIndex] < node.splitAttValue ? 0
            : 1], attVals);
  }

  protected void generateHeader() {
    FastVector<Attribute> attributes = new FastVector<>();
    FastVector<String> nominalAttVals = new FastVector<>();
    for (int i = 0; i < this.numValsPerNominalOption.getValue(); i++) {
      nominalAttVals.addElement("value" + (i + 1));
    }
    for (int i = 0; i < this.numNominalsOption.getValue(); i++) {
      attributes.addElement(new Attribute("nominal" + (i + 1),
          nominalAttVals));
    }
    for (int i = 0; i < this.numNumericsOption.getValue(); i++) {
      attributes.addElement(new Attribute("numeric" + (i + 1)));
    }
    FastVector<String> classLabels = new FastVector<>();
    for (int i = 0; i < this.numClassesOption.getValue(); i++) {
      classLabels.addElement("class" + (i + 1));
    }
    attributes.addElement(new Attribute("class", classLabels));
    this.streamHeader = new InstancesHeader(new Instances(
        getCLICreationString(InstanceStream.class), attributes, 0));
    this.streamHeader.setClassIndex(this.streamHeader.numAttributes() - 1);
  }

  protected void generateRandomTree() {
    Random treeRand = new Random(this.treeRandomSeedOption.getValue());
    ArrayList<Integer> nominalAttCandidates = new ArrayList<>(
        this.numNominalsOption.getValue());
    for (int i = 0; i < this.numNominalsOption.getValue(); i++) {
      nominalAttCandidates.add(i);
    }
    double[] minNumericVals = new double[this.numNumericsOption.getValue()];
    double[] maxNumericVals = new double[this.numNumericsOption.getValue()];
    for (int i = 0; i < this.numNumericsOption.getValue(); i++) {
      minNumericVals[i] = 0.0;
      maxNumericVals[i] = 1.0;
    }
    this.treeRoot = generateRandomTreeNode(0, nominalAttCandidates,
        minNumericVals, maxNumericVals, treeRand);
  }

  protected Node generateRandomTreeNode(int currentDepth,
      ArrayList<Integer> nominalAttCandidates, double[] minNumericVals,
      double[] maxNumericVals, Random treeRand) {
    if ((currentDepth >= this.maxTreeDepthOption.getValue())
        || ((currentDepth >= this.firstLeafLevelOption.getValue()) && (this.leafFractionOption.getValue() >= (1.0 - treeRand
            .nextDouble())))) {
      Node leaf = new Node();
      leaf.classLabel = treeRand.nextInt(this.numClassesOption.getValue());
      return leaf;
    }
    Node node = new Node();
    int chosenAtt = treeRand.nextInt(nominalAttCandidates.size()
        + this.numNumericsOption.getValue());
    if (chosenAtt < nominalAttCandidates.size()) {
      node.splitAttIndex = nominalAttCandidates.get(chosenAtt);
      node.children = new Node[this.numValsPerNominalOption.getValue()];
      ArrayList<Integer> newNominalCandidates = new ArrayList<>(
          nominalAttCandidates);
      newNominalCandidates.remove(new Integer(node.splitAttIndex));
      newNominalCandidates.trimToSize();
      for (int i = 0; i < node.children.length; i++) {
        node.children[i] = generateRandomTreeNode(currentDepth + 1,
            newNominalCandidates, minNumericVals, maxNumericVals,
            treeRand);
      }
    } else {
      int numericIndex = chosenAtt - nominalAttCandidates.size();
      node.splitAttIndex = this.numNominalsOption.getValue()
          + numericIndex;
      double minVal = minNumericVals[numericIndex];
      double maxVal = maxNumericVals[numericIndex];
      node.splitAttValue = ((maxVal - minVal) * treeRand.nextDouble())
          + minVal;
      node.children = new Node[2];
      double[] newMaxVals = maxNumericVals.clone();
      newMaxVals[numericIndex] = node.splitAttValue;
      node.children[0] = generateRandomTreeNode(currentDepth + 1,
          nominalAttCandidates, minNumericVals, newMaxVals, treeRand);
      double[] newMinVals = minNumericVals.clone();
      newMinVals[numericIndex] = node.splitAttValue;
      node.children[1] = generateRandomTreeNode(currentDepth + 1,
          nominalAttCandidates, newMinVals, maxNumericVals, treeRand);
    }
    return node;
  }

  @Override
  public void getDescription(StringBuilder sb, int indent) {
    // TODO Auto-generated method stub
  }
}
