/*
 * Written by Tomasz Wrzosek and released to the public domain, as explained
 * at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.util.io.test;

import edu.emory.mathcs.util.io.BufferedDataInputStream;
import edu.emory.mathcs.util.io.BufferedDataOutputStream;
import java.io.*;


/**
 * <p>Title: Test class</p>
 * <p>Description: This class may be used to test edu.emory.mathcs.util.io.BufferedDataInput/OutputStream
 * classes. It writes to and reads from a file portions of data. First data is
 * written using java.io.DataOutputStream and read with BufferedInputStream.
 * The second test excercises a symmetric behaviour on BufferedDataOutpuStream
 * and java.io.DataInputStream, respectively. The last test uses both Emory
 * streams.</p>
 * <p>If implementation is correct results printed on the screen should show it.</p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: Emory University, Mathematics & Computer Science Department</p>
 * @author Tomasz Wrzosek
 * @version 1.0
 */

public class BufferedDataStreamTest {
  /* primitive types */
  static final boolean o = true;
  static final byte b = (byte) 12;
  static final char c = 'a';
  static final short s = (short)2453;
  static final int i = 88989;
  static final long l = 10000L;
  static final double d = 3.1415d;
  static final float f = 1/3f;
  static final String str = "Ala ma kota "+((char)0x81)+((char)0xcFF5);

  /* arrays */
  static final boolean [] ao = new boolean [] {true, true, false};
  static byte [] ab;
  static final char [] ac = new char [] {'a', 'c','z','!','"','A'};
  static final short [] as = new short [] {(short)2453, (short) -231};
  static final int [] ai = new int [] {-192, 1982, 99822, 0x0921, 0x003, 0xFe};
  static final long [] al = new long [] {10000L,-0x0982L, 876712127727327L};
  static final double [] ad = new double [] {3.1415d,-10e-100,2.3452d};
  static final float [] af = new float [] {1/3f,-9/12653f,99091/13f};


  public static void main(String[] args) {
    ab = new byte [1024-4-1]; //-4 for length -1 to make a mess :)
    for (int i=0;i<ab.length;i++) {
      ab[i]=(byte)(i%256);
    }
    OutputStream os; InputStream is;
    System.out.println("TEST 1: write: DataOutputStream, read: BufferedDataInputStream");
    try {
      write((DataOutput)(os = new DataOutputStream(new FileOutputStream("testFile.bts"))),false);
      os.close();
      read((DataInput)(is = new BufferedDataInputStream(new FileInputStream("testFile.bts"))),false);
      is.close();
    } catch (IOException ex) {
      ex.printStackTrace();
    }
    System.out.println("\nTEST 2: write: BufferedDataOutputStream, read: DataInputStream");
    try {
      write((DataOutput)(os = new BufferedDataOutputStream(new FileOutputStream("testFile.bts"))),false);
      os.close();
      read((DataInput)(is = new DataInputStream(new FileInputStream("testFile.bts"))),false);
      is.close();
    } catch (IOException ex) {
      ex.printStackTrace();
    }
    System.out.println("\nTEST 3: write: BufferedDataOutputStream, read: BufferedDataInputStream");
    try {
      write((DataOutput)(os = new BufferedDataOutputStream(new FileOutputStream("testFile.bts"))),true);
      os.close();
      read((DataInput)(is = new BufferedDataInputStream(new FileInputStream("testFile.bts"))),true);
      is.close();
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }

  private static void write(DataOutput os, boolean buff) throws IOException {
    os.writeBoolean(o);
    os.writeByte(b);
    os.writeChar(c);
    os.writeShort(s);
    os.writeInt(i);
    os.writeLong(l);
    os.writeDouble(d);
    os.writeFloat(f);
    os.writeUTF(str);

    if (buff) {
      BufferedDataOutputStream bos =(BufferedDataOutputStream) os;
      bos.writeInt(ab.length);
      bos.writeBytes(ab,0,ab.length);
      bos.writeInt(ao.length);
      bos.writeBooleans(ao,0,ao.length);
      bos.writeInt(ac.length);
      bos.writeChars(ac,0,ac.length);
      bos.writeInt(as.length);
      bos.writeShorts(as,0,as.length);
      bos.writeInt(ai.length);
      bos.writeInts(ai,0,ai.length);
      bos.writeInt(al.length);
      bos.writeLongs(al,0,al.length);
      bos.writeInt(af.length);
      bos.writeFloats(af,0,af.length);
      bos.writeInt(ad.length);
      bos.writeDoubles(ad,0,ad.length);
    }

    os.writeLong(l);
    os.writeBoolean(o);
    os.writeByte(b);
    os.writeChar(c);
    os.writeShort(s);
    os.writeInt(i);
    os.writeDouble(d);
    os.writeFloat(f);
    os.writeUTF(str);
  }

  private static void read(DataInput is, boolean buff) throws IOException {
    System.out.println("orig: "+o+" read: "+is.readBoolean());
    System.out.println("orig: "+b+" read: "+is.readByte());
    System.out.println("orig: "+c+" read: "+is.readChar());
    System.out.println("orig: "+s+" read: "+is.readShort());
    System.out.println("orig: "+i+" read: "+is.readInt());
    System.out.println("orig: "+l+" read: "+is.readLong());
    System.out.println("orig: "+d+" read: "+is.readDouble());
    System.out.println("orig: "+f+" read: "+is.readFloat());
    System.out.println("orig: "+str+" read: "+is.readUTF());

    if (buff) {
      BufferedDataInputStream bis =(BufferedDataInputStream) is;
      System.out.print("array orig: ");
      printArray(ab);
      System.out.print("array read: ");
      int lng = bis.readInt();
      Object ob = bis.readBytes(new byte[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(ao);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readBooleans(new boolean[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(ac);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readChars(new char[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(as);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readShorts(new short[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(ai);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readInts(new int[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(al);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readLongs(new long[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(af);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readFloats(new float[lng],0,lng);
      printArray(ob);

      System.out.print("array orig: ");
      printArray(ad);
      System.out.print("array read: ");
      lng = bis.readInt();
      ob = bis.readDoubles(new double[lng],0,lng);
      printArray(ob);
    }

    System.out.println("orig: "+l+" read: "+is.readLong());
    System.out.println("orig: "+o+" read: "+is.readBoolean());
    System.out.println("orig: "+b+" read: "+is.readByte());
    System.out.println("orig: "+c+" read: "+is.readChar());
    System.out.println("orig: "+s+" read: "+is.readShort());
    System.out.println("orig: "+i+" read: "+is.readInt());
    System.out.println("orig: "+d+" read: "+is.readDouble());
    System.out.println("orig: "+f+" read: "+is.readFloat());
    System.out.println("orig: "+str+" read: "+is.readUTF());
  }

  static void printArray(Object obj) {
    if (!obj.getClass().isArray()) {
      System.out.print("NOT AN ARRAY");
      return;
    }
    Class komp = obj.getClass().getComponentType();
    if (byte.class == komp) {
      printBytes ((byte[])obj);
    } else if (boolean.class == komp) {
      printBooleans ((boolean[])obj);
    } else if (char.class == komp) {
      printChars ((char[])obj);
    } else if (short.class == komp) {
      printShorts ((short[])obj);
    } else if (int.class == komp) {
      printInts ((int[])obj);
    } else if (long.class == komp) {
      printLongs ((long[])obj);
    } else if (float.class == komp) {
      printFloats ((float[])obj);
    } else if (double.class == komp) {
      printDoubles ((double[])obj);
    }
  }

  private static void printBooleans(boolean [] arr) {
    System.out.print("Array of booleans. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printBytes(byte [] arr) {
    System.out.print("Array of bytes. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printChars(char [] arr) {
    System.out.print("Array of chars. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printShorts(short [] arr) {
    System.out.print("Array of shorts. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printInts(int [] arr) {
    System.out.print("Array of ints. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printLongs(long [] arr) {
    System.out.print("Array of longs. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printFloats(float [] arr) {
    System.out.print("Array of floats. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }

  private static void printDoubles(double [] arr) {
    System.out.print("Array of doubles. Length: "+arr.length+". Elements ");
    int maxToPrint = Math.min(5, arr.length);
    for (int i=0;i<maxToPrint;i++) {
      System.out.print(arr[i]+",");
    }
    System.out.println("...");
  }
}
