package yi.util.data;

import java.util.*;

public class Conversion {

  public static LinkedList asLinkedList(Object[] array) {
    LinkedList list = new LinkedList();
    for (int i=0; i<array.length; i++) {
      list.add(array[i]);
    }
    return list;
  }
  /**
   * Convert 2D int array to 1D int array
   * @param data2D the 2D data
   * @param width the width of the 2D Matrix (the 2nd dimension of data2D)
   * @param height the heigth of the 2D Matrix (the 1st dimension of data2D)
   * @return the 1D array
   */
  public static int[] from2Dto1D(int[][] data2D, int width, int height) {
    int[] data1D = new int[width * height];
    int count = 0;
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        data1D[count++] = data2D[h][w];
      }
    }
    return data1D;
  }

  public static double[] from2Dto1D(double[][] data2D, int width, int height) {
    double[] data1D = new double[width * height];
    int count = 0;
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        data1D[count++] = data2D[h][w];
      }
    }
    return data1D;
  }

  /**
   * Convert 1D int array to 2D int array
   * @param data1D the 1D data
   * @param width the width of the 2D Matrix (the 2nd dimension of data2D)
   * @param height the heigth of the 2D Matrix (the 1st dimension of data2D)
   * @return the 2D array
   */
  public static int[][] from1Dto2D(int[] data1D, int width, int height) {
    int[][] data2D = new int[height][width];
    int count = 0;
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        data2D[h][w] = data1D[count++];
      }
    }
    return data2D;
  }

  public static double[][] from1Dto2D(double[] data1D, int width, int height) {
    double[][] data2D = new double[height][width];
    int count = 0;
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        data2D[h][w] = data1D[count++];
      }
    }
    return data2D;
  }
  /**
   * Swap the x and y components of each element: from (x,y) to (y,x)
   * @param data the data to be swapped
   * @param width the matrix width
   * @param height the matrix height
   * @return the swapped data
   */
  public static int[][] swapXandY(int[][] data, int width, int height) {
    int[][] rst = new int[width][height];
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        rst[w][h] = data[h][w];
      }
    }
    return rst;
  }

  /**
   * Swap the x and y components of each element: from (x,y) to (y,x)
   * @param data the data to be swapped
   * @param width the matrix width
   * @param height the matrix height
   * @return the swapped data
   */
  public static double[][] swapXandY(double[][] data, int width, int height) {
    double[][] rst = new double[width][height];
    for (int h=0; h<height; h++) {
      for (int w=0; w<width; w++) {
        rst[w][h] = data[h][w];
      }
    }
    return rst;
  }

  /**
   * Convert Integer array to int array
   * @param data
   * @return
   */
  public static int[] toIntArray(Integer[] Integer_array) {
    int[] int_array = new int[Integer_array.length];
    for (int i=0; i<int_array.length; i++) int_array[i] = Integer_array[i].intValue();
    return int_array;
  }

  /**
   * Convert a Integer Collection to an int array
   * @param data
   * @return
   */
  public static int[] toIntArray(Collection c) {
    Object[] objects = c.toArray();
    int[] int_array = new int[c.size()];
    Iterator i = c.iterator(); int count = 0;
    while (i.hasNext()) int_array[count++] = ((Integer)i.next()).intValue();
    return int_array;
  }

  /**
   * Convert a Double Collection to doublearray
   * @param data
   * @return
   */
  public static double[] toDoubleArray(Double[] Double_array) {
    double[] double_array = new double[Double_array.length];
    for (int i=0; i<double_array.length; i++) double_array[i] = Double_array[i].doubleValue();
    return double_array;
  }

  /**
   * Convert a Double Collection to doublearray
   * @param data
   * @return
   */
  public static double[] toDoubleArray(Collection c) {
    Object[] objects = c.toArray();
    double[] double_array = new double[c.size()];
    Iterator i = c.iterator(); int count = 0;
    while (i.hasNext()) double_array[count++] = ((Double)i.next()).doubleValue();
    return double_array;
  }

  /**
   * Convert a Double array Collection to 2D doublearray
   * @param data
   * @return
   */
  public static double[][] to2DDoubleArray(Collection c) {
    Object[] objects = c.toArray();
    double[][] double_array = new double[c.size()][];
    Iterator i = c.iterator(); int count = 0;
    while (i.hasNext()) {
      double_array[count++] = (double[]) i.next();
    }
    return double_array;
  }

  /**
   * Convert a Double array Collection to 2D doublearray
   * @param data
   * @return
   */
  public static int[][] to2DIntArray(Collection c) {
    Object[] objects = c.toArray();
    int[][] array = new int[c.size()][];
    Iterator i = c.iterator(); int count = 0;
    while (i.hasNext()) {
      array[count++] = (int[]) i.next();
    }
    return array;
  }

  /**
   * Convert a Integer Collection to an Integer array
   * @param data
   * @return
   */
  public static Integer[] toIntegerArray(Collection c) {
    Object[] objects = c.toArray();
    Integer[] integers = new Integer[objects.length];
    for (int i=0; i<integers.length; i++) integers[i] = (Integer)objects[i];
    return integers;
  }

  /**
   * Convert a String Collection to an Integer array
   * @param data
   * @return
   */
  public static String[] toStringArray(Collection c) {
    Object[] objects = c.toArray();
    String[] strings = new String[objects.length];
    for (int i=0; i<strings.length; i++) strings[i] = (String)objects[i];
    return strings;
  }

  /**
   * Convert an int array to an Integer array
   * @param data
   * @return
   */
  public static Integer[] toIntegerArray(int[] data) {
    Integer[] integers = new Integer[data.length];
    for (int i=0; i<integers.length; i++) integers[i] = new Integer(data[i]);
    return integers;
  }

  public static int[] toInt(double[] data) {
    int[] rst = new int[data.length];
    for (int i=0; i<data.length; i++) rst[i] = (int)Math.round(data[i]);
    return rst;
  }

  public static int[][] toInt(double[][] data) {
    int[][] rst = new int[data.length][];
    for (int i=0; i<data.length; i++) rst[i] = toInt(data[i]);
    return rst;
  }

  public static double[] toDouble(int[] data) {
    double[] rst = new double[data.length];
    for (int i=0; i<data.length; i++) rst[i] = (int)Math.round(data[i]);
    return rst;
  }

  public static double[][] toDouble(int[][] data) {
    double[][] rst = new double[data.length][];
    for (int i=0; i<data.length; i++) rst[i] = toDouble(data[i]);
    return rst;
  }

  /**
   * Return a new array which only contains the non-empty cells of the given
   * array
   * @return
   */
  public static Object[] removeEmptyCells(Object[] the_array) {
    // non empty cell number
    int non_empty_count = 0;
    for (int i=0; i<the_array.length; i++) {
      if (the_array[i] != null) non_empty_count ++;
    }

    // construct the new array
    Object[] new_array = new Object[non_empty_count];
    int count = 0;
    for (int i=0; i<the_array.length; i++) {
      if (the_array[i] != null) new_array[count++] = the_array[i];
    }
    return new_array;
  }

  /**
   * return a string to represent the integer with the fixed length.  The left
   * with be filled with "0".  If the string length should be bigger than the
   * given length to represent the integer, then just keep the format. (no
   * cutting)
   * @param integer
   * @param length
   * @return
   */
  public static String toString(int integer, int length) {
    String str = Integer.toString(integer);
    while (str.length() < length) {
      str = "0" + str;
    }
    return str;
  }

  public static String[] toStringArray(Object[] strs) {
    return toStringArray(Arrays.asList(strs));
  }

  public static LinkedList toLinkedList(double[][] data) {
    LinkedList list = new LinkedList();
    for (int i=0; i<data.length; i++) {
      list.add(data[i]);
    }
    return list;
  }

  public static LinkedList toLinkedList(int[][] data) {
    LinkedList list = new LinkedList();
    for (int i=0; i<data.length; i++) {
      list.add(data[i]);
    }
    return list;
  }

  public static LinkedList toLinkedList(int[] data) {
    LinkedList list = new LinkedList();
    for (int i=0; i<data.length; i++) {
      list.add(new Integer(data[i]));
    }
    return list;
  }

  public static LinkedList toLinkedList(String[] data) {
    LinkedList list = new LinkedList();
    for (int i=0; i<data.length; i++) {
      list.add(data[i]);
    }
    return list;
  }
}