

package Graphics;

import java.lang.*;
import java.awt.*;
import java.io.*;


public class Scenefile 
{
  private String filespec;

  private int max_vertices;
  private Vector vertices[];
  private int nr_vertices = 0;
  
  private DataInputStream my_data;
  private FileInputStream my_file;
  private static final int MAX_KEYWORD_LENGTH = 32;



  public Scenefile(String name)
  {
    try {
      my_file = new FileInputStream(name);
    }
    catch (FileNotFoundException e) {
      System.out.println(e.getMessage());
    }
    my_data = new DataInputStream(my_file);
  }



  public Scenefile(InputStream in_stream)
  {
    my_data = new DataInputStream(in_stream);
  }



  public void skip_line()
  {
    try {
      my_data.readLine();
    }
    catch (IOException e) {
      System.out.println(e.getMessage());
    }
  }



  public boolean is_token_char(char k)
  {
    return (Character.isLowerCase(k) || Character.isUpperCase(k) ||
	    Character.isDigit(k) || (k == '.') || (k == '_') || (k == '-') || (k=='\\') || (k==':')
      || k=='/');
  }



  public String get_token()
  {
    StringBuffer token = new StringBuffer(MAX_KEYWORD_LENGTH);

    char k;
    try {
      do {
	k = (char) my_data.readUnsignedByte();
	if (k == '#') skip_line();
      } while (!is_token_char(k));

      token.append(k);
      do {
	k = (char) my_data.readUnsignedByte();
	if (is_token_char(k))
	  token.append(k);
	else
	  if (k == '#') skip_line();
      } while (is_token_char(k));
    }  // try
    
    catch (EOFException e) {}
    catch (IOException e) {
      System.out.println(e.getMessage());
    }

    return token.toString().toLowerCase();
  }



  public boolean accept(String wanted)
  {
    String token = get_token();
    wanted.toLowerCase();
    if (token.equals(wanted)) return true;
    else {
      System.out.println("Parse error: expected: " + 
			 wanted + ", read: " + token);
      return false;
    }
  }



  public int get_int()
  {
    int number = 0;
    String token = new String("");

    try {
      token = get_token();
      number = Integer.parseInt(token);
    }
    catch (NumberFormatException e) {
      System.out.println("Parse error: number expected, read: "
			 + token);
    }
    return number;
  }



  public double get_double()
  {
    double number = 0;
    String token = new String("");

    try {
      token = get_token();
      number = Double.valueOf(token).doubleValue();
    }
    catch (NumberFormatException e) {
      System.out.println("Parse error: number expected, read: "
			 + token);
    }
    return number;
  }



  public Vector get_vector()
  {
    double temp[] = new double[3];
    Vector result = new Vector();

    try {
      for(int i=0; i<3; i++) {
	temp[i] = my_data.readDouble();
      }
    }  // try
    catch (EOFException e) {}
    catch (IOException e) {
      System.out.println(e.getMessage());
    }
    result.set(temp[0], temp[1], temp[2]);
    return result;
  }


  public void parse(Scene s)
  {
    boolean done = false;

    if (!accept("scene")) return;
    
    while (!done) {
      String token = get_token();

      if (token.equals("max_vertices")) {
	max_vertices = get_int();
	vertices = new Vector[max_vertices];
      }
      else if (token.equals("vertex")) {
	vertices[nr_vertices] = 
	  new Vector(get_double(), get_double(), get_double());
	nr_vertices++;
      }
      else if (token.equals("object"))
	parse_object(s);
       else if (token.equals("global"))
	parse_global(s);
      else if (token.equals("end_scene"))
	done = true;
      else {
	System.out.println("Parse error: unknown keyword " + token);
	done = true;
      }
    }
  }  

   public void parse_global(Scene scene)
  {
    boolean done = false;


    
    while (!done) {
      String token = get_token();

      if (token.equals("totalframes")) {
	      scene.totalframes = get_int();
      }
      else if (token.equals("ka")) {
        scene.k_a = get_int();
      }
       else if (token.equals("kd")) {
        scene.k_d = get_int();
      }
       else if (token.equals("ks")) {
        scene.k_s = get_int();
      }
       else if (token.equals("ns")) {
        scene.n_s = get_int();
      }
       else if (token.equals("wireframe")) {
        scene.wireframe = get_int();
      }


      else if (token.equals("camera")) {
       scene.cameraLocation=new Vector(get_double(),get_double(),get_double());
           scene.cameraLookat=new Vector(get_double(),get_double(),get_double());

      }
      else if (token.equals("end_global"))
	done = true;
      else {
	System.out.println("Parse error: unknown keyword " + token);
	done = true;
      }
    }
  }  


  public void parse_anim(Object obj,Scene scene)
  {
    boolean done = false;

     System.out.println("adding animation");
    while (!done) {
      String token = get_token();

      if (token.equals("rotatex")) {
      System.out.println("Adding rotatex");
      
	      Vector location=new Vector(get_double(),get_double(),get_double());
        double angle=get_double()/scene.totalframes;
        angle*=Math.PI/180;
        Matrix r=new Matrix();
        r.rotate_xl(location,angle);
          System.out.println("Angle : " + angle*180/Math.PI);
        obj.r_transform=r.matrix_multiply(obj.r_transform);
      }

      else if (token.equals("rotatey")) {
	      Vector location=new Vector(get_double(),get_double(),get_double());
        double angle=get_double()/scene.totalframes;
        angle*=Math.PI/180;
        Matrix r=new Matrix();
        r.rotate_yl(location,angle);
        obj.r_transform=r.matrix_multiply(obj.r_transform);
      }
      
      else if (token.equals("rotatez")) {
	      Vector location=new Vector(get_double(),get_double(),get_double());
        double angle=get_double()/scene.totalframes;
        angle*=Math.PI/180;
        Matrix r=new Matrix();
        r.rotate_zl(location,angle);
        obj.r_transform=r.matrix_multiply(obj.r_transform);
      }
       else if (token.equals("path")) {
        obj.path[obj.npaths++]=new Vector(get_double(),get_double(),get_double());
        
      }



      else if (token.equals("end_anim"))
	done = true;
      else {
	System.out.println("Parse error: unknown keyword " + token);
	done = true;
      }
    }
  }

  private void parse_object(Scene s)
  {
    Object obj = new Object();
    obj.reset();
    boolean done = false;

    while (!done) {
      String token = get_token();
      if (token.equals("polygon"))     // polyhon
	parse_polygon(obj);
      else if (token.equals("colour")) {     // set color
	Color colour = new Color(get_int(), get_int(), get_int());
	obj.set_Color(colour);
      }
         else if (token.equals("wireframe")) {     // set wireframe accuracy
		obj.set_wireframe(get_int());
      }
      else if (token.equals("rotatex")) {    // rotatex object

	obj.rotate_x(new Vector(get_double(), get_double(), get_double()),
		       get_double());
      }
       else if (token.equals("rotatey")) {   // rotatey object

	obj.rotate_y(new Vector(get_double(), get_double(), get_double()),
		       get_double());
      }
       else if (token.equals("rotatez")) {    // rotatez object

	obj.rotate_z(new Vector(get_double(), get_double(), get_double()),
		       get_double());
      }

       else if (token.equals("translate")) {    // rotatez object

	obj.translate(new Vector(get_double(), get_double(), get_double()) );
      }



      else if (token.equals("sphere")) {     // sphere object
	obj.set_sphere(new Vector(get_double(), get_double(), get_double()),
		       get_double());
      }

      else if (token.equals("superellipse")) {     // superellipse object
	obj.create_superellipse(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),get_double(),get_double(),get_double(),obj.get_colour(0));
      }

         else if (token.equals("donut")) {     // superellipse object
	obj.create_donut(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),get_double(),obj.get_colour(0));
      }
        else if (token.equals("cone")) {     // cone object
	obj.create_cone(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),obj.get_colour(0));
      }
        else if (token.equals("cylinder")) {     // cylinder object
	obj.create_cylinder(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),obj.get_colour(0));
      }

      else if (token.equals("pyramid")) {
	obj.create_pyramid(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),get_double(),obj.get_colour(0));
      }
       else if (token.equals("box")) {
	obj.create_box(new Vector(get_double(), get_double(), get_double()),
		       get_double(),get_double(),get_double(),obj.get_colour(0));
      }
          else if (token.equals("terrain")) {
	obj.create_terrain(get_double(), get_double(), get_double(),
		     get_double(),get_double(),obj.get_colour(0));
      }

         else if (token.equals("mapterrain")) {
	obj.create_mapterrain(get_double(), get_double(), get_double(),
		     get_double(),get_double(),get_token(),obj.get_colour(0));
      }
         else if (token.equals("line")) {
	obj.create_line(new Vector(get_double(), get_double(), get_double()),
		     new Vector(get_double(), get_double(), get_double()),obj.get_colour(0));
      }
         else if (token.equals("tree")) {
        	obj.draw(get_double(),get_double(),get_double(),get_double(),get_double(),get_double(),get_int(),get_int());
  
      }

      else if (token.equals("light")) {
            Vector pos=new Vector(get_double(),get_double(),get_double());
           Vector col=new Vector(get_double(),get_double(),get_double());

           s.lights[s.nr_lights]=new Object();
          s.lights[s.nr_lights].setLight(pos,col);
          obj=s.lights[s.nr_lights];
          s.nr_lights++;

      }
      else if (token.equals("anim")) {     // animation
          parse_anim(obj,s);
      }


      else if (token.equals("end_object"))
	done = true;
      else {
	System.out.println("Parse error: unknown keyword " + token);
	done = true;
      }
    }  // while
    if(obj.light==null)
      s.add_object(obj);
  }  // parse_object



  private void parse_polygon(Object obj)
  {
    MyPolygon p = new MyPolygon();
    boolean done = false;
    String token = new String("");

    try {
      while (!done) {
	token = get_token();
	if (token.equals("end"))
	  done = true;
	else {
	  int index;
	  index = Integer.parseInt(token);
	  p.addPoint(vertices[index]);
	}
      }  // while
      obj.add_polygon(p);
    }
    catch (NumberFormatException e) {
      System.out.println("Parse error: vertex index expected, read: "
			 + token);
      done = true;
    }  // catch
  }  // parse_polygon


}  


	
