/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.apache.samoa.instances;

/*
 * #%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%
 */

/**
 * 
 * @author abifet
 */
public class SparseInstanceData implements InstanceData {

  public SparseInstanceData(double[] attributeValues, int[] indexValues, int numberAttributes) {
    this.attributeValues = attributeValues;
    this.indexValues = indexValues;
    this.numberAttributes = numberAttributes;
  }

  public SparseInstanceData(int length) {
    this.attributeValues = new double[length];
    this.indexValues = new int[length];
  }

  protected double[] attributeValues;

  public double[] getAttributeValues() {
    return attributeValues;
  }

  public void setAttributeValues(double[] attributeValues) {
    this.attributeValues = attributeValues;
  }

  public int[] getIndexValues() {
    return indexValues;
  }

  public void setIndexValues(int[] indexValues) {
    this.indexValues = indexValues;
  }

  public int getNumberAttributes() {
    return numberAttributes;
  }

  public void setNumberAttributes(int numberAttributes) {
    this.numberAttributes = numberAttributes;
  }

  protected int[] indexValues;
  protected int numberAttributes;

  @Override
  public int numAttributes() {
    return this.numberAttributes;
  }

  @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;
    }
  }

  @Override
  public boolean isMissing(int indexAttribute) {
    return Double.isNaN(this.value(indexAttribute));
  }

  @Override
  public int numValues() {
    return this.attributeValues.length;
  }

  @Override
  public int index(int indexAttribute) {
    return this.indexValues[indexAttribute];
  }

  @Override
  public double valueSparse(int indexAttribute) {
    return this.attributeValues[indexAttribute];
  }

  @Override
  public boolean isMissingSparse(int indexAttribute) {
    return Double.isNaN(this.valueSparse(indexAttribute));
  }

  /*
   * @Override public double value(Attribute attribute) { return
   * value(attribute.index()); }
   */

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

  @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;
    }
  }

}
