import java.awt.*;
import java.lang.*;
import java.io.*;
import java.util.*;

public class TransactionReport
{
  protected Date occurred;
  protected long amtDollar, amtCent, finalBalanceDollar, finalBalanceCent;
  protected long sourceAccountNo, destinationAccountNo;
  protected long cardNo;
  protected String transactionType;

  private static String fileName = new String ("transactions.rpt");
  private static String headers = new String ("Source\t\tDestination\tCard\t\t\tDate\t\t\tTrans\tAmt\tFinal\nAccount\t\tAccount\t\tNumber\t\t\t\t\t\tType\t\tBalance\n");

  private FileInputStream	fileIn;
  private FileOutputStream	fileOut;
  private FilterInputStream	filterIn;
  private FilterOutputStream	filterOut;
  private DataInputStream	dataIn;
  private DataOutputStream	dataOut;
  private BufferedInputStream	bufferedIn;
  private BufferedOutputStream	bufferedOut;


  public TransactionReport ()
  {
    this (0, 0, 0, 0, 0, 0, 0, 0, 0, "null", 0, 0);
  }

  public TransactionReport (long sourceAccountNo, long destinationAccountNo, long cardNo, String transactionType, long amtCent, long finalBalance)
  {
    occurred = new Date ();
    this.transactionType = transactionType;
    this.amtDollar = amtCent/100;
    this.amtCent = amtCent%100;
    this.finalBalanceDollar = finalBalance/100;
    this.finalBalanceCent = finalBalance%100;
    this.sourceAccountNo = sourceAccountNo;
    this.destinationAccountNo = destinationAccountNo;
    this.cardNo = cardNo;
  }

  public TransactionReport (long sourceAccountNo, long cardNo, String transactionType, long amtCent, long finalBalance)
  {
    occurred = new Date ();
    this.transactionType = transactionType;
    this.amtDollar = amtCent/100;
    this.amtCent = amtCent%100;
    this.finalBalanceDollar = finalBalance/100;
    this.finalBalanceCent = finalBalance%100;
    this.sourceAccountNo = sourceAccountNo;
    this.destinationAccountNo = sourceAccountNo;
    this.cardNo = cardNo;
  }

  public TransactionReport (int year, int month, int day, int hour, int minute, int second, long sourceAccountNo, long destinationAccountNo, long cardNo, String transactionType, long amtCent, long finalBalance)
  {
    occurred = new Date (year, month, day, hour, minute, second);
    this.transactionType = transactionType;
    this.amtDollar = amtCent/100;
    this.amtCent = amtCent%100;
    this.finalBalanceDollar = finalBalance/100;
    this.finalBalanceCent = finalBalance%100;
    this.sourceAccountNo = sourceAccountNo;
    this.destinationAccountNo = destinationAccountNo;
    this.cardNo = cardNo;
  }

  public TransactionReport (int year, int month, int day, int hour, int minute, int second, long sourceAccountNo, long cardNo, String transactionType, long amtCent, long finalBalance)
  {
    occurred = new Date (year, month, day, hour, minute, second);
    this.transactionType = transactionType;
    this.amtDollar = amtCent/100;
    this.amtCent = amtCent%100;
    this.finalBalanceDollar = finalBalance/100;
    this.finalBalanceCent = finalBalance%100;
    this.sourceAccountNo = sourceAccountNo;
    this.destinationAccountNo = sourceAccountNo;
    this.cardNo = cardNo;
  }


  public String toString ()
  {
    String out = new String();
    String temp = new String();

    out += sourceAccountNo + "\t";
    out += destinationAccountNo + "\t";
    out += cardNo + "\t";
    out += occurred.toString() + "\t";
    out += transactionType + "\t";

    if (amtCent == 0)
      temp = "00";
    else
      temp = Long.toString (amtCent);
    out += "$"+ amtDollar +"."+ temp + "\t";

    if (finalBalanceCent == 0)
      temp = "00";
    else
      temp = Long.toString (finalBalanceCent);
    out += "$"+ finalBalanceDollar +"."+ temp + "\t";

    out.trim();

    return out;
  }

  public void addTransaction ()
  {
    try
    {
      fileOut = new FileOutputStream (fileName, true);
      bufferedOut = new BufferedOutputStream (fileOut);
      dataOut = new DataOutputStream (bufferedOut);

      try
      {
        dataOut.writeUTF (this.toString()+"\n");
      }
      catch (IOException e)
      {
        System.out.println ("Could not write transaction "+ this.toString());
      }
    }
    catch (FileNotFoundException e)
    {
      System.out.println ("Could not open file to write transaction "+ this.toString());
    }
    finally
    {
      try
      {
        dataOut.close();
        bufferedOut.close();
        fileOut.close();
      }
      catch (IOException e)
      {
        System.out.println ("Could not close dataOut, bufferedOut or fileOut during transaction "+ this.toString());
      }
    }
  }

  public void setTransaction (String transaction)
  {
    String tempSourceAccountNo = new String();
    String tempDestinationAccountNo = new String();
    String tempCardNo = new String();
    String tempYear = new String();
    String tempMonth = new String();
    String tempDate = new String();
    String tempHours = new String();
    String tempMinutes = new String();
    String tempSeconds = new String();
    String tempAmtDollar = new String();
    String tempAmtCent = new String();
    String tempFinalBalanceDollar = new String();
    String tempFinalBalanceCent = new String();
    String tempTransactionType = new String();

    int i, flag = 0, start = 0;
    boolean add = true;

    while (!(Character.isDigit(transaction.charAt(start))) && !(Character.isLetter(transaction.charAt(start))))
      start++;

    for (i = start; i < transaction.length(); i++)
    {
      if (!(Character.isDigit(transaction.charAt(i))) && !(Character.isLetter(transaction.charAt(i))))
      {
        add = false;
        flag++;
      }
      else
        add = true;

//System.out.println ("i == "+ i +"\ttransaction.charAt(i) == "+ transaction.charAt(i) +"\tflag == "+ flag +"\tadd == "+ add);
      if (add)
      {
        switch (flag)
        {
          case (0):
            tempSourceAccountNo += transaction.charAt(i);
            break;
          case (1):
            tempDestinationAccountNo += transaction.charAt(i);
            break;
          case (2):
            tempCardNo += transaction.charAt(i);
            break;
          case (4):
            tempMonth += transaction.charAt(i);
            break;
          case (5):
            tempDate += transaction.charAt(i);
            break;
          case (6):
            tempHours += transaction.charAt(i);
            break;
          case (7):
            tempMinutes += transaction.charAt(i);
            break;
          case (8):
            tempSeconds += transaction.charAt(i);
            break;
          case (10):
            tempYear += transaction.charAt(i);
            break;
          case (11):
            tempTransactionType += transaction.charAt(i);
            break;
          case (12):
            if (tempTransactionType.equalsIgnoreCase ("Transfer"))
            {
              while ((Character.isDigit(transaction.charAt(i))) || (Character.isLetter(transaction.charAt(i))))
                i++;
              tempTransactionType = "Transfer Funds";
            }
            break;
          case (13):
            tempAmtDollar += transaction.charAt(i);
            break;
          case (14):
            tempAmtCent += transaction.charAt(i);
            break;
          case (16):
            tempFinalBalanceDollar += transaction.charAt(i);
            break;
          case (17):
            tempFinalBalanceCent += transaction.charAt(i);
            break;
        }
      }
    }

    this.sourceAccountNo = Long.decode(tempSourceAccountNo).longValue();
    this.destinationAccountNo = Long.decode(tempDestinationAccountNo).longValue();
    this.cardNo = Long.decode(tempCardNo).longValue();

    this.occurred = new Date (tempYear +" "+ tempMonth +" "+ tempHours +":"+ tempMinutes +":"+ tempSeconds +" "+ tempDate);

    this.amtDollar = Long.decode(tempAmtDollar).longValue();
    this.amtCent = Long.decode(tempAmtCent).longValue();
    this.finalBalanceDollar = Long.decode(tempFinalBalanceDollar).longValue();
    this.finalBalanceCent = Long.decode(tempFinalBalanceCent).longValue();
    this.transactionType = tempTransactionType;
  }

  public void searchDate (Date begin, Date end)
  {
    TransactionReport trpt = new TransactionReport();
    String transactionFromFile = new String();

    try
    {
      fileIn = new FileInputStream (fileName);
      bufferedIn = new BufferedInputStream (fileIn);
      dataIn = new DataInputStream (bufferedIn);

      System.out.println (headers);
      /*  read trpt from file  */
      /*  while not EOF  */

      try
      {
        transactionFromFile = dataIn.readUTF();
        while (transactionFromFile != null)
        {
          trpt.setTransaction (transactionFromFile);
          if ((trpt.occurred.after(begin)) && (trpt.occurred.before(end)))
            System.out.println (trpt.toString());
          transactionFromFile = dataIn.readUTF();
        }
      }
      catch (IOException e)
      {
        System.out.println ("\n");
        //System.out.println ("Could not read dataIn...");
      }
    }
    catch (FileNotFoundException e)
    {
      System.out.println ("Could not open file to read transaction "+ this.toString());
    }
    finally
    {
      try
      {
        dataIn.close();
        bufferedIn.close();
        fileIn.close();
      }
      catch (IOException e)
      {
        System.out.println ("Could not close dataIn, bufferedIn or fileIn during transaction "+ this.toString());
      }
    }
  }


  public void searchAccount (long accountNo)
  {
    TransactionReport trpt = new TransactionReport();
    String transactionFromFile = new String();

    try
    {
      fileIn = new FileInputStream (fileName);
      bufferedIn = new BufferedInputStream (fileIn);
      dataIn = new DataInputStream (bufferedIn);

      System.out.println (headers);
      /*  read trpt from file  */
      /*  while not EOF  */

      try
      {
        transactionFromFile = dataIn.readUTF();
        while (transactionFromFile != null)
        {
          trpt.setTransaction (transactionFromFile);
          if (trpt.sourceAccountNo == accountNo)
            System.out.println (trpt.toString());
          transactionFromFile = dataIn.readUTF();
        }
        System.out.println ("\n");
      }
      catch (IOException e)
      {
        System.out.println ("\n");
        //System.out.println ("Could not read dataIn...");
      }
    }
    catch (FileNotFoundException e)
    {
      System.out.println ("Could not open file to read transaction "+ this.toString());
    }
    finally
    {
      try
      {
        dataIn.close();
        bufferedIn.close();
        fileIn.close();
      }
      catch (IOException e)
      {
        System.out.println ("Could not close dataIn, bufferedIn or fileIn during transaction "+ this.toString());
      }
    }
  }


  public void searchCard (long cardNo)
  {
    TransactionReport trpt = new TransactionReport();
    String transactionFromFile = new String();

    try
    {
      fileIn = new FileInputStream (fileName);
      bufferedIn = new BufferedInputStream (fileIn);
      dataIn = new DataInputStream (bufferedIn);

      System.out.println (headers);
      /*  read trpt from file  */
      /*  while not EOF  */

      try
      {
        transactionFromFile = dataIn.readUTF();
        while (transactionFromFile != null)
        {
          trpt.setTransaction (transactionFromFile);
          if (trpt.cardNo == cardNo)
            System.out.println (trpt.toString());
          transactionFromFile = dataIn.readUTF();
        }
        System.out.println ("\n");
      }
      catch (IOException e)
      {
        System.out.println ("\n");
        //System.out.println ("Could not read dataIn...");
      }
    }
    catch (FileNotFoundException e)
    {
      System.out.println ("Could not open file to read transaction "+ this.toString());
    }
    finally
    {
      try
      {
        dataIn.close();
        bufferedIn.close();
        fileIn.close();
      }
      catch (IOException e)
      {
        System.out.println ("Could not close dataIn, bufferedIn or fileIn during transaction "+ this.toString());
      }
    }
  }


  public static void main (String args [])
  {
    TransactionReport trpt = new TransactionReport();

    System.out.print (trpt.toString()+"\n");
    trpt.addTransaction();

    Long acct1 = new Long ("524198427313");
    Long acct2 = new Long ("943276439234");

    trpt = new TransactionReport (1999-1900, 8, 16, 13, 12, 37, acct1.longValue(), acct1.longValue(), "W", (long)5000, (long)20000);
    System.out.print (trpt.toString()+"\n");
    trpt.addTransaction();

    trpt = new TransactionReport (1999-1900, 8, 21, 15, 8, 12, acct1.longValue(), acct2.longValue(), acct1.longValue(), "TF", (long)5000, (long)15000);
    System.out.print (trpt.toString()+"\n");
    trpt.addTransaction();

    trpt = new TransactionReport (1999-1900, 8, 17, 18, 20, 6, acct2.longValue(), acct2.longValue(), "D", (long)3000, (long)12000);
    System.out.print (trpt.toString()+"\n");
    trpt.addTransaction();

    Date begin = new Date (1999-1900, 7, 6, 0, 0, 0);
    Date end = new Date (1999-1900, 8, 20, 23, 59, 59);
    trpt.searchDate (begin, end);
    trpt.searchAccount (acct2.longValue());
    trpt.searchCard (acct1.longValue());
  }
}
