/*
 * 
 * Datei:   Eingabe.java
 * 
 * ---------------------------------
 * 
 * Datum:           $Date: 2004/05/13 14:03:48 $
 * Autor:           Simon Tiffert 
 * Prüfungsnummer:  40
 * Firma:           T-Systems
 * eMail-Adresse:   simon.tiffert@t-systems.com
 * Version:         $Revision: 1.23 $
 * 
 * ---------------------------------
 * 
 */
package main.eingabe;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import main.tools.eingabe.MyLineNumberReader;
import main.verarbeitung.IsSperrfeldException;
import main.verarbeitung.IsStartpunktException;
import main.verarbeitung.Matrix;
import main.verarbeitung.WrongDimensionException;

/**
 * Diese Klasse liest die Eingabedaten aus einer Datei aus und 
 * erstellt die Matrix, die für die spätere Verarbeitung gebraucht 
 * wird.
 * 
 * @version $Revision: 1.23 $
 * @author Simon Tiffert
 */
public class Eingabe
{
  /** Feld für Matrix */
  private Matrix matrix;

  /**
  * Konstruktor, welcher die Matrix übernimmt, die Datei zuweist und 
  * mit diesen Daten die Funktion leseDaten() aufruft
  * 
  * @param matrix Zentrale Datenstruktur mit Matrix
  * @param dateiName Name der Eingabedatei
  * @throws UnexpectedCharacterException Unerwartetes Zeichen
  * @throws UnexpectedLineException Unerwartete Zeile
  * @throws UnknownCharacterException Unbekanntes Zeichen
  * @throws TooFewCharactersException Zuwenig Zeichen angegeben
  * @throws TooFewSperrfelderException Zuwenig Sperrfelder angegeben
  * @throws FileNotFoundException Datei wurde nicht gefunden
  * @throws IOException Fehler bei der Eingabe
  * @throws IsSperrfeldException Doppeldefinition von Sperrfeld
  * @throws IsStartpunktException Sperrfeld auf Startfeld definiert
  * @throws WrongDimensionException Falsche Dimensionsangaben
  */
  public Eingabe(Matrix matrix, String dateiName)
    throws
      UnexpectedCharacterException,
      UnexpectedLineException,
      UnknownCharacterException,
      TooFewCharactersException,
      TooFewSperrfelderException,
      FileNotFoundException,
      IOException,
      IsSperrfeldException,
      IsStartpunktException,
      WrongDimensionException
  {
    // Weise übergebene Parameter den Variablen zu
    this.matrix = matrix;
    File file = new File(dateiName);

    // Rufe Funktion zur Abarbeitung auf
    leseDaten(new FileReader(file));
  }

  /**
   * Diese Funktion liest die Eingabedatei aus.
   * Außerdem findet hier ein Teil der Syntaxüberprüfung statt, 
   * welche die Eingabedaten auf Korrektheit überprüft.
   *  
   * @param stream Reader auf Eingabedatei
   * @throws UnexpectedCharacterException Unerwartetes Zeichen
   * @throws UnexpectedLineException Unerwartete Zeile
   * @throws UnknownCharacterException Unbekanntes Zeichen
   * @throws TooFewCharactersException Zuwenig Zeichen angegeben
   * @throws TooFewSperrfelderException Zuwenig Sperrfelder angegeben
   * @throws FileNotFoundException Datei wurde nicht gefunden
   * @throws IOException Fehler bei der Eingabe
   * @throws IsSperrfeldException Doppeldefinition von Sperrfeld
   * @throws IsStartpunktException Sperrfeld auf Startfeld definiert
   * @throws WrongDimensionException Falsche Dimensionsangaben
   */
  private void leseDaten(Reader stream)
    throws
      UnexpectedCharacterException,
      UnexpectedLineException,
      UnknownCharacterException,
      IOException,
      TooFewCharactersException,
      TooFewSperrfelderException,
      IsSperrfeldException,
      IsStartpunktException,
      WrongDimensionException
  {
    // Aktuell gelesene Zeile
    String zeile = "";

    // Anzahl gesperrter Felder
    int gesperrteFelder = 0;

    // Koordinaten des aktuellen Punktes
    int y = 0, x = 0;

    // Lies die Datei zeilenweise und speichere dabei die 
    // aktuelle Zeilennummer
    LineNumberReader lineNumber = new MyLineNumberReader(stream, "**");

    // StringTokenizer, der einen String in Token aufteilt	
    StringTokenizer st;

    // Lies die erste Zeile aus der Eingabedatei und verarbeite sie
    if ((zeile = lineNumber.readLine()) != null)
    {
      st = new StringTokenizer(zeile);
    }
    // Wenn dies nicht klappt, ist die Datei leer und eine Exception
    // wird geworfen
    else
    {
      throw new TooFewCharactersException(
        "" + lineNumber.getLineNumber());
    }

    // Lies die Zahlen, fange ab, wenn dabei Probleme auftauchen
    try
    {
      // Lies die Dimensionsangaben
      y = Integer.parseInt(st.nextToken());
      x = Integer.parseInt(st.nextToken());
    }
    catch (NoSuchElementException e)
    {
      throw new TooFewCharactersException(
        "" + lineNumber.getLineNumber());
    }
    catch (Exception e)
    {
      throw new UnknownCharacterException(
        "" + lineNumber.getLineNumber());
    }

    // Erstelle die Matrix in der Dimension y*x
    matrix.setMatrix(y, x);

    // Wenn noch weitere Zeichen in der Zeile sind, werfe Fehler
    if (st.hasMoreTokens())
    {
      throw new UnexpectedCharacterException(
        "" + lineNumber.getLineNumber());
    }

    // Lese die zweite Zeile für den Startpunkt
    // wenn keine Eingabedaten da sind, werfe Exception
    if ((zeile = lineNumber.readLine()) != null)
    {
      st = new StringTokenizer(zeile);
    }
    else
    {
      throw new TooFewCharactersException(
        "" + lineNumber.getLineNumber());
    }

    // Lies die Zahlen, fange ab, wenn dabei Probleme auftauchen
    try
    {
      // Lies Koordinaten des Startpunktes      
      y = Integer.parseInt(st.nextToken()) - 1;
      x = Integer.parseInt(st.nextToken()) - 1;
    }
    catch (NoSuchElementException e)
    {
      throw new TooFewCharactersException(
        "" + lineNumber.getLineNumber());
    }
    catch (Exception e)
    {
      throw new UnknownCharacterException(
        "" + lineNumber.getLineNumber());
    }

    // Setze den Startpunkt für die Sprungfolge
    matrix.setStartpunkt(y, x);

    // Wenn noch weitere Zeichen in der Zeile sind, werfe Fehler
    if (st.hasMoreTokens())
    {
      throw new UnexpectedCharacterException(
        "" + lineNumber.getLineNumber());
    }

    // Lies Anzahl gesperrter Felder ein (optional)
    if ((zeile = lineNumber.readLine()) != null)
    {
      // Lies die Zahl, fange ab, wenn dabei Probleme auftauchen
      try
      {
        gesperrteFelder = Integer.parseInt(zeile);
      }
      catch (Exception e)
      {
        throw new UnknownCharacterException(
          "" + lineNumber.getLineNumber());
      }

      // Besetze gesperrte Felder der Matrix mit '-1'
      for (int i = 0; i < gesperrteFelder; i++)
      {
        if ((zeile = lineNumber.readLine()) != null)
        {
          st = new StringTokenizer(zeile);

          // Lies die Zahlen, fange ab, wenn dabei Probleme auftauchen
          try
          {
            // Lies Koordinaten,  setze den Punkt in der Matrix
            y = Integer.parseInt(st.nextToken()) - 1;
            x = Integer.parseInt(st.nextToken()) - 1;
          }
          catch (NoSuchElementException e)
          {
            throw new TooFewCharactersException(
              "" + lineNumber.getLineNumber());
          }
          catch (Exception e)
          {
            throw new UnknownCharacterException(
              "" + lineNumber.getLineNumber());
          }

          // Wenn noch weitere Zeichen in der Zeile sind, werfe Fehler
          if (st.hasMoreTokens())
          {
            throw new UnexpectedCharacterException(
              "" + lineNumber.getLineNumber());
          }

          // Setze das ermittelte Sperrfeld
          matrix.setSperrfeld(y, x);
        }
        else
        {
          throw new TooFewSperrfelderException();
        }
      }
    }

    // Wenn noch weitere Zeichen am Ende der Datei sind, werfe Fehler
    if (lineNumber.readLine() != null)
    {
      throw new UnexpectedLineException(
        "" + lineNumber.getLineNumber());
    }
  }
}
