/* Copyright (c) 1997-2004
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   $Project: polymake $$Id: SimpleGeometryParser.java,v 1.3 2004/08/23 13:13:13 thilosch Exp $
*/

package de.tuberlin.polymake.common;

import jv.geom.PgPointSet;
import jv.geom.PgPolygonSet;
import jv.vecmath.PdVector;
import jv.vecmath.PiVector;

import java.util.*;
import java.lang.NumberFormatException;
import java.io.IOException;

/**
 * A simple line parser.
 *
 * @author Thilo Schr&ouml;eder
 */
public class SimpleGeometryParser extends PolymakeParser {
    
    public SimpleGeometryParser(String[] params) {
	super(params);
    }

    public PgPolygonSet parse(java.io.BufferedReader in) 
	throws IOException {
	
	PgPolygonSet m_geom = new PgPolygonSet();

	String line;
	error = null;
	warning = null;
	Vector points = new Vector();
	boolean end_flag = false;

	while(!end_flag && (line = in.readLine())!= null) {
	    if(System.getProperty("polymake.debug") != null &&
	       System.getProperty("polymake.debug").equalsIgnoreCase("max")) {
		System.out.println("jv<" + line);
	    }
	    line.trim();
	    switch(line.charAt(0)) {
	    case 'n':
		name = line.substring(2);
		//System.out.println("JV got name: " +name);
		m_geom.setName(name);
		break;
	    case '#':
		int n_points = Integer.parseInt(line.substring(2));
		break;
	    case 'e':
		error = line.substring(2);
		break;
	    case 'w':
		warning = line.substring(2);
		break;
	    case 'p':
		PdVector point = parsePoint(line.substring(2));
		points.add(point);
		break;
	    case 'l':
		PiVector polygon = parsePolygon(line.substring(2));
		m_geom.addPolygon(polygon);
		break;
	    case 'f':
		parameters.setProperty("facet",line.substring(2));
		break;
	    case 's':
		{
		    StringTokenizer st = new StringTokenizer(line.substring(2));
		    String key = st.nextToken();
		    if(parameters.keySet().contains(key)) {
			parameters.setProperty(key,st.nextToken());
		    }
		    break;
		}
	    case 'i':
		{
		    StringTokenizer st = new StringTokenizer(line.substring(2));
		    String key = st.nextToken();
		    if(parameters.keySet().contains(key)) {
			iparameters.setProperty(key,st.nextToken());
		    }
		    break;
		}
	    case 'x':
		{
		    end_flag = true;
		    break;
		}
	    default:
	    }
	}
	Object[] pts = points.toArray();
	for(int i = 0; i < pts.length; ++i) {
	    m_geom.addVertex((PdVector)pts[i]);
	}
	return m_geom;
    }
    
    public Vector getFacet() {
	return parseFacet(parameters.getProperty("facet"));
    }

    /**
     * Parses a <code>String</code> into a <code>PdVector</code> containing coordinates
     * and possibly a label.
     *
     * @param str the string to be parsed
     * @return a <code>PdVector</code> containing the coordinates and possibly a label
     * @exception NumberFormatException if there are non-double coordinates
     */
    public static PdVector parsePoint(String str) throws NumberFormatException {
	StringTokenizer tokenizer = new StringTokenizer(str);
	PdVector point = new PdVector();
	while (tokenizer.hasMoreTokens()) {
	    String token = tokenizer.nextToken();
	    if(token.equals("l")) {
		point.setName(tokenizer.nextToken());
	    } else {
		point.addEntry(Double.parseDouble(token));
	    }
	}
	//	System.out.println(point);
	return point;
    }

    /**
     * Parses a <code>String</code> into a <code>PiVector</code> the vertices of
     * a polygon
     *
     * @param str the string to be parsed
     * @return a <code>PiVector</code> containing the vertices of a polygon
     * @exception NumberFormatException if there are non-integer vertices
     */
    public static PiVector parsePolygon(String str) throws NumberFormatException {
	StringTokenizer tokenizer = new StringTokenizer(str);
	PiVector polygon = new PiVector();
	while (tokenizer.hasMoreTokens()) {
	    String token = tokenizer.nextToken();
	    polygon.addEntry(Integer.parseInt(token));
	}
	return polygon;
    }
    
    /**
     * Parses a <code>String</code> into a <code>Set</code> containing its
     * vertices.
     *
     * @param str the string to be parsed
     * @return a <code>Vector</code> containing the vertices
     * @exception NumberFormatException if there are non-int vertices
     */
    public static Vector parseFacet(String str) throws NumberFormatException {
	StringTokenizer tokenizer = new StringTokenizer(str);
	Vector facet = new Vector();
	while (tokenizer.hasMoreTokens()) {
	    facet.add(new Integer(tokenizer.nextToken()));
	}
	return facet;
    }
    
    public static String write(PgPointSet geom, Properties params) {
	String msg = new String();
	if(geom != null) {
	    msg += "n " + geom.getName() + "\n";
	    PdVector[] vertices = geom.getVertices();
	    for(int i = 0; i < vertices.length; ++i) {
		double[] vertex = vertices[i].getEntries();
		msg += "p";
		for(int j = 0; j < vertex.length; ++j) {
		    msg += " " + vertex[j];
		}
		if(vertices[i].getName() != null) {
		    msg += " l " + vertices[i].getName();
		}
		msg += "\n";
	    }
	}
	
	if(params != null) {
	    for(Iterator it = params.keySet().iterator(); it.hasNext();) {
		String param = (String)it.next();
		String value = params.getProperty(param);
		if(value != null) msg += "s " + param + " " + value + "\n";
	    }
	}
	msg += "x\n";
	return msg;
    }

    public static String write(String name, Properties params) {
	String msg = new String();
	msg += "n " + name + "\n";

	if(params != null) {
	    for(Iterator it = params.keySet().iterator(); it.hasNext();) {
		String param = (String)it.next();
		String value = params.getProperty(param);
		if(value != null) msg += "s " + param + " " + value + "\n";
	    }
	}
	
	msg += "x\n";
	return msg;
    }

    public static String write(String name, String command, double value) {
	String msg = new String();
	msg += "n " + name + "\n";
	msg += "s " + command + " " + value + "\n";	
	msg += "x\n";
	return msg;
    }

    public static String write(PgPointSet geom,Vector marked, Properties params) {
	String msg = new String();
	if(geom != null) {
	    msg += "n " + geom.getName() + "\n";
	    PdVector[] vertices = geom.getVertices();
	    for(int i = 0; i < vertices.length; ++i) {
		double[] vertex = vertices[i].getEntries();
		msg += "p";
		for(int j = 0; j < vertex.length; ++j) {
		    msg += " " + vertex[j];
		}
		if(vertices[i].getName() != null) {
		    msg += " l " + vertices[i].getName();
		}
		msg += "\n";
	    }
	    msg += "f ";
	    Iterator it = marked.iterator();
	    while(it.hasNext()) {
		msg += (String)it.next() + " ";
	    }
	    msg += "\n";
	}
	
	if(params != null) {
	    for(Iterator it = params.keySet().iterator(); it.hasNext();) {
		String param = (String)it.next();
		String value = params.getProperty(param);
		if(value != null) msg += "s " + param + " " + value + "\n";
	    }
	}
	msg += "x\n";
	return msg;
    }

    public static String writeFacet(String name, Vector verts) {
	String msg = new String();
	msg += "n " + name + "\n";
	msg += "f ";
	Iterator it = verts.iterator();
	while(it.hasNext()) {
	    msg += (String)it.next() + " ";
	}
	msg += "\n" + "x\n";
	return msg;
    }
}
