/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package org.apache.samoa.instances;

public class SparseInstanceData implements InstanceData {

  /**
   * The attribute values.
   */
  protected double[] attributeValues;
  /**
   * The index values.
   */
  protected int[] indexValues;
  /**
   * The number of attributes.
   */
  protected int numberAttributes;

  /**
   * Instantiates a new sparse instance data.
   *
   * @param attributeValues
   *          the attribute values
   * @param indexValues
   *          the index values
   * @param numberAttributes
   *          the number attributes
   */
  public SparseInstanceData(double[] attributeValues, int[] indexValues, int numberAttributes) {
    this.attributeValues = attributeValues;
    this.indexValues = indexValues;
    this.numberAttributes = numberAttributes;
  }

  /**
   * Instantiates a new sparse instance data.
   *
   * @param length
   *          the length
   */
  public SparseInstanceData(int length) {
    this.attributeValues = new double[length];
    this.indexValues = new int[length];
  }

  /**
   * Gets the attribute values.
   *
   * @return the attribute values
   */
  public double[] getAttributeValues() {
    return attributeValues;
  }

  /**
   * Sets the attribute values.
   *
   * @param attributeValues
   *          the new attribute values
   */
  public void setAttributeValues(double[] attributeValues) {
    this.attributeValues = attributeValues;
  }

  /**
   * Gets the index values.
   *
   * @return the index values
   */
  public int[] getIndexValues() {
    return indexValues;
  }

  /**
   * Sets the index values.
   *
   * @param indexValues
   *          the new index values
   */
  public void setIndexValues(int[] indexValues) {
    this.indexValues = indexValues;
  }

  /**
   * Gets the number attributes.
   *
   * @return the number attributes
   */
  public int getNumberAttributes() {
    return numberAttributes;
  }

  /**
   * Sets the number of attributes.
   *
   * @param numberAttributes
   *          the new number attributes
   */
  public void setNumberAttributes(int numberAttributes) {
    this.numberAttributes = numberAttributes;
  }

  /**
   * Gets the number of attributes.
   *
   * @return the int
   */
  @Override
  public int numAttributes() {
    return this.numberAttributes;
  }

  /**
   * Value.
   *
   * @param indexAttribute
   *          the index attribute
   * @return the double
   */
  @Override
  public double value(int indexAttribute) {
    int location = locateIndex(indexAttribute);
    //return location == -1 ? 0 : this.attributeValues[location];
    //      int index = locateIndex(attIndex);
    if ((location >= 0) && (indexValues[location] == indexAttribute)) {
      return attributeValues[location];
    } else {
      return 0.0;
    }
  }

  /**
   * Checks if is missing.
   *
   * @param indexAttribute
   *          the index attribute
   * @return true, if is missing
   */
  @Override
  public boolean isMissing(int indexAttribute) {
    return Double.isNaN(this.value(indexAttribute));
  }

  /**
   * Num values.
   *
   * @return the int
   */
  @Override
  public int numValues() {
    return this.attributeValues.length;
  }

  /**
   * Index.
   *
   * @param indexAttribute
   *          the index attribute
   * @return the int
   */
  @Override
  public int index(int indexAttribute) {
    return this.indexValues[indexAttribute];
  }

  /**
   * Value sparse.
   *
   * @param indexAttribute
   *          the index attribute
   * @return the double
   */
  @Override
  public double valueSparse(int indexAttribute) {
    return this.attributeValues[indexAttribute];
  }

  /**
   * Checks if is missing sparse.
   *
   * @param indexAttribute
   *          the index attribute
   * @return true, if is missing sparse
   */
  @Override
  public boolean isMissingSparse(int indexAttribute) {
    return Double.isNaN(this.valueSparse(indexAttribute));
  }

  /**
   * To double array.
   *
   * @return the double[]
   */
  @Override
  public double[] toDoubleArray() {
    double[] array = new double[numAttributes()];
    for (int i = 0; i < numValues(); i++) {
      array[index(i)] = valueSparse(i);
    }
    return array;
  }

  /**
   * Sets the value.
   *
   * @param attributeIndex
   *          the attribute index
   * @param d
   *          the d
   */
  @Override
  public void setValue(int attributeIndex, double d) {
    int index = locateIndex(attributeIndex);
    if (index(index) == attributeIndex) {
      this.attributeValues[index] = d;
    } else {
      // We need to add the value
    }
  }

  /**
   * Locates the greatest index that is not greater than the given index.
   *
   * @return the internal index of the attribute index. Returns -1 if no index with this property could be found
   */
  public int locateIndex(int index) {

    int min = 0;
    int max = this.indexValues.length - 1;

    if (max == -1) {
      return -1;
    }

    // Binary search
    while ((this.indexValues[min] <= index) && (this.indexValues[max] >= index)) {
      int current = (max + min) / 2;
      if (this.indexValues[current] > index) {
        max = current - 1;
      } else if (this.indexValues[current] < index) {
        min = current + 1;
      } else {
        return current;
      }
    }
    if (this.indexValues[max] < index) {
      return max;
    } else {
      return min - 1;
    }
  }

  /**
   * Deletes an attribute at the given position (0 to numAttributes() - 1).
   * 
   * @param position
   *          the attribute's position
   */
  @Override
  public void deleteAttributeAt(int position) {

    int index = locateIndex(position);

    this.numberAttributes--;
    if ((index >= 0) && (indexValues[index] == position)) {
      int[] tempIndices = new int[indexValues.length - 1];
      double[] tempValues = new double[attributeValues.length - 1];
      System.arraycopy(indexValues, 0, tempIndices, 0, index);
      System.arraycopy(attributeValues, 0, tempValues, 0, index);
      for (int i = index; i < indexValues.length - 1; i++) {
        tempIndices[i] = indexValues[i + 1] - 1;
        tempValues[i] = attributeValues[i + 1];
      }
      indexValues = tempIndices;
      attributeValues = tempValues;
    } else {
      int[] tempIndices = new int[indexValues.length];
      double[] tempValues = new double[attributeValues.length];
      System.arraycopy(indexValues, 0, tempIndices, 0, index + 1);
      System.arraycopy(attributeValues, 0, tempValues, 0, index + 1);
      for (int i = index + 1; i < indexValues.length; i++) {
        tempIndices[i] = indexValues[i] - 1;
        tempValues[i] = attributeValues[i];
      }
      indexValues = tempIndices;
      attributeValues = tempValues;
    }
  }

  @Override
  public void insertAttributeAt(int position) {
    if ((position < 0) || (position > numAttributes())) {
      throw new IllegalArgumentException("Can't insert attribute: index out "
              + "of range");
    }
    int index = locateIndex(position);

    this.numberAttributes++;
    if ((index >= 0) && (indexValues[index] == position)) {
      int[] tempIndices = new int[indexValues.length + 1];
      double[] tempValues = new double[attributeValues.length + 1];
      System.arraycopy(indexValues, 0, tempIndices, 0, index);
      System.arraycopy(attributeValues, 0, tempValues, 0, index);
      tempIndices[index] = position;
      tempValues[index] = Double.NaN; //Missing Value
      for (int i = index; i < indexValues.length; i++) {
        tempIndices[i + 1] = indexValues[i] + 1;
        tempValues[i + 1] = attributeValues[i];
      }
      indexValues = tempIndices;
      attributeValues = tempValues;
    } else {
      int[] tempIndices = new int[indexValues.length + 1];
      double[] tempValues = new double[attributeValues.length + 1];
      System.arraycopy(indexValues, 0, tempIndices, 0, index + 1);
      System.arraycopy(attributeValues, 0, tempValues, 0, index + 1);
      tempIndices[index + 1] = position;
      tempValues[index + 1] = Double.NaN; //Missing Value
      for (int i = index + 1; i < indexValues.length; i++) {
        tempIndices[i + 1] = indexValues[i] + 1;
        tempValues[i + 1] = attributeValues[i];
      }
      indexValues = tempIndices;
      attributeValues = tempValues;
    }
  }

  @Override
  public InstanceData copy() {
    return new SparseInstanceData(this.attributeValues, this.indexValues, this.numberAttributes);
  }

}
