package yi.ai.cluster;

import yi.ds.DataRange;
import java.util.*;

/**
 * OneDCluster is a data structure to store the 1D data clustering results.
 * Each cluster is represented by a DataRange
 * @see yi.ai.cluster.Clusters
 */
public class OneDClusters {
  /**
   * The length of data (how many vectors to be clustered)
   */
  int m_dataLength;

  /**
   * The resultant cluster number.
   */
  int m_clusterNum;

  /**
   * Clusters represented by the data ranges.
   */
  DataRange[] m_clusters;

  /**
   * The data->cluster_index map
   */
  int[] m_clusterMap;

  public OneDClusters(int cluster_num, DataRange[] clusters, int data_len, int[] map) {
    m_clusterNum = cluster_num;
    m_clusters = clusters;

    m_dataLength = data_len;
    m_clusterMap = map;
  }

  /**
   * Init the clusters with a collection of DataRanges
   * @param data_ranges
   * @param data_len
   * @param map
   */
  public OneDClusters(Collection data_ranges, int data_len, int[] map) {

    DataRange[] data_regions_array = new DataRange[data_ranges.size()];
    Iterator i = data_ranges.iterator();
    int count = 0;
    while (i.hasNext()) {
      data_regions_array[count++] = (DataRange)i.next();
    }

    m_clusters = data_regions_array;
    m_clusterNum = data_regions_array.length;

    m_dataLength = data_len;
    m_clusterMap = map;
  }

  public int getClusterNum() {
    return m_clusterNum;
  }

  public DataRange[] getClusters() {
    return m_clusters;
  }

  public int[] getClusterMap() {
    return m_clusterMap;
  }

  public int getDataLength() {
    return m_dataLength;
  }

  /**
   * Look up the data ranges of the clusters, and return which cluster the data
   * belongs to.  Return -1 if can't find a corresponding cluster.
   * @param data
   * @return
   */
  public int getLabel(int data) {
    for (int i=0; i<m_clusters.length; i++) {
      int lower = m_clusters[i].getLowerBound();
      int higher = m_clusters[i].getHigherBound();
      if (lower <= higher) {
        if (lower <= data && data < higher) return i;
      } else {
        if (lower <= data || data < higher) return i;
      }
    }
    return -1; // can't find any cluster for it.
  }
}