package yi.ds.hd;

import java.util.*;

/**
 * HighDimensionCoordinates is used to represent a high-dimensional coordinates.
 * For example, {1, 2, 2} in a 3D place.  The coordinates only takes integer
 * format
 */
public class IntArray {
  int[] m_coordinates;

  public IntArray(int[] coordinates) {
    m_coordinates = coordinates;
  }

  public IntArray(String array_str) {
    StringTokenizer tokenizer = new StringTokenizer(array_str, ", []");
    m_coordinates = new int[tokenizer.countTokens()];
    int count = 0;
    while (tokenizer.hasMoreTokens()) {
      m_coordinates[count++] = Integer.parseInt(tokenizer.nextToken());
    }
  }

  public static IntArray concat(IntArray old_data, int new_data) {
    return new IntArray(concat(old_data.m_coordinates, new int[] {new_data}));
  }

  public static int[] concat(int[] old_data, int[] new_data) {
    int old_data_len = old_data.length;
    int new_data_len = new_data.length;
    // new array
    int[] new_coord = new int[old_data_len + new_data_len];

    // copy the arrays
    System.arraycopy(old_data, 0, new_coord, 0, old_data_len);
    System.arraycopy(new_data, 0, new_coord, old_data_len, new_data_len);
    return new_coord;
  }

  public static IntArray concat(
    IntArray old_data, IntArray new_data) {
      return new IntArray(concat(old_data.m_coordinates, new_data.m_coordinates));
  }

  public int[] getCoordinates() {
    return m_coordinates;
  }

  public int length() {return m_coordinates.length;}

  public int elementAt(int index) {return m_coordinates[index];}

  public IntArray subArray(int from, int length) {
    int[] new_array = new int[length];
    System.arraycopy(m_coordinates, from, new_array, 0, length);
    return new IntArray(new_array);
  }

  public static int[] subArray(int[] array, int from, int length) {
    int[] new_array = new int[length];
    System.arraycopy(array, from, new_array, 0, length);
    return new_array;
  }

  public int getMax() {
    return yi.stat.StatUtil.maximum(m_coordinates);
  }


  /**
   * Test whether two HighDimensionCoordinates are the same.  Important for Set,
   * Map, etc.
   * @param o the object to be compared
   * @return whetherh there are the same
   */
  public boolean equals (Object o) {
    if(this == o) {  // Step 1: Perform an == test
      return true;
    }

    if(!(o instanceof IntArray)) {  // Step 2: Instance of check
      return false;
    }

    IntArray c2 = (IntArray) o;  //Step 3: Cast argument

    // Step 4: For each important field, check to see if they are equal
    // For primitives use ==
    // For objects use equals() but be sure to also
    // handle the null case first
    if (m_coordinates.length != c2.m_coordinates.length) return false;
    for (int i=0; i<m_coordinates.length; i++)  {
      if (m_coordinates[i] != c2.m_coordinates[i]) return false;
    }
    return true;
  }

  /**
   * Return the hash code for the HighDimensionCoordinates object
   * @return the hash code
   */
  public int hashCode() {
    int code = 0;
    for (int i=0; i<m_coordinates.length; i++) {
      code <<= 3;
      code += m_coordinates[i];
    }
    return code;
  }

  public String toString() {
    StringBuffer s = new StringBuffer();
    for (int i=0; i<m_coordinates.length; i++) {
      if (i != 0) s.append(',');
      s.append(m_coordinates[i]);
    }
    return s.toString();
  }


}