/* $Id: XMLToLineConverter.java 722 2013-08-05 04:15:48Z shayashi $ */
package smart_gs.util;

import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import smart_gs.GSConstants;
import smart_gs.logical.GSResource;
import smart_gs.logical.LineSegment;
import smart_gs.logical.LineSegmentForEdit;
import smart_gs.logical.Spread;
import sml_editor.logical.LineDirection;

public class XMLToLineConverter {
	
	private Spread spread;
	
	public XMLToLineConverter(Spread spread){
		this.spread = spread;
	}
	
	public Pair<LineDirection,List<LineSegment>> getLines(File file){
		LineDirection lineDirection = LineDirection.UNDEFINED;
		NodeList lines = null;
		List<LineSegment> results_lines = new ArrayList<LineSegment>();
		DocumentBuilder builder = null;
		Document document = null;

		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			document = builder.parse(file);
			NodeList line_direction_nodes = document.getElementsByTagName("lineDirection");
			Node node0, child0;
			
			if (line_direction_nodes == null
					|| line_direction_nodes.getLength() != 1 ) {
				System.out.printf("Line Direction in %s is not given%n", file);
				System.out.println("The Line Direction is set the defualt UNDEFINED");
			} else if( ! (line_direction_nodes.item(0).getNodeType() == Node.ELEMENT_NODE 
					&& line_direction_nodes.item(0).getChildNodes().getLength() == 1
					&& line_direction_nodes.item(0).getFirstChild().getNodeType() == Node.TEXT_NODE) ) {
				System.out.printf("Line Direction format in %s is illegal%n",file);
				System.out.println("The Line Direction is set the defualt UNDEFINED");
			} else {

				node0 = line_direction_nodes.item(0);

				if (node0 == null) {
					System.out.printf("Line Direction specification XML-element for %s is missing (1: for debugging)%n", file);
					System.out.println("The Line Direction is set the defualt UNDEFINED");
				} else	{

					child0 = node0.getFirstChild();

					if (child0 == null) {
						System.out.printf("Line Direction specification XML-element for %s has NULL-value (2: for debugging)%n", file);
						System.out.println("The Line Direction is set the defualt UNDEFINED");
					} else {

						String value0 = child0.getNodeValue();

						if (value0 == null) {
							System.out.printf("Line Direction specification for %s has  (3: for debugging)%n", file);
							System.out.println("The Line Direction is set the defualt UNDEFINED");
						} else {

							String directionString = value0.trim();

							if ( ! directionString.equalsIgnoreCase("horizontal") && ! directionString.equalsIgnoreCase("vertical")) {
								System.out.printf("Line Direction %s in %s is illegal%n", directionString, file);
							} else if (directionString.equalsIgnoreCase("horizontal")) {
								lineDirection = LineDirection.HORIZONTAL;
							} else if (directionString.equalsIgnoreCase("vertical")) {
								lineDirection = LineDirection.VERTICAL;
							}
						}
					}
				}
			}
			lines = document.getElementsByTagName("vertexes");
			for(int i=0;i<lines.getLength();i++){
				if(lines.item(i).getNodeType() == Node.ELEMENT_NODE){
					LineSegment segment = this.getLineSegment((Element)lines.item(i), i);
					results_lines.add(segment);
				}
			}
		} catch(ParserConfigurationException e){
			e.printStackTrace();
			return null;
		} catch (SAXException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
			//	e.printStackTrace();
		}
		return new Pair<LineDirection,List<LineSegment>>(lineDirection,results_lines);
	}
	
	
	private LineSegment getLineSegment(Element element, int index){
		List<Point2D> points = new ArrayList<Point2D>();
		String uri = element.getAttribute("uri");
		String originalURI = element.getAttribute(GSResource.ORIGINAL_URI);
		NodeList nodes = element.getElementsByTagName("vertex");
		double x = 0.0 ,y = 0.0;
		for(int i=0;i<nodes.getLength();i++){
			if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE){
				Element e = (Element)nodes.item(i);
				NodeList childs = e.getChildNodes();
				for(int j=0;j<childs.getLength();j++){
					if(childs.item(j).getNodeType() == Node.ELEMENT_NODE){
						Element elem = (Element)childs.item(j);
						if(elem.getNodeName().equals("x")){
							x = new Double(elem.getTextContent());
						}
						else if(elem.getNodeName().equals("y")){
							y = new Double(elem.getTextContent());
							points.add(new Point2D.Double(x,y));
						}
					}
				}
			}
		}
		return new LineSegment(spread,points,uri,originalURI,index);
	}

	public Pair<LineDirection,List<LineSegmentForEdit>> getLinesForEdit(File file){
		LineDirection lineDirection = LineDirection.UNDEFINED;
		NodeList lines = null;
		List<LineSegmentForEdit> results_lines = new ArrayList<LineSegmentForEdit>();
		DocumentBuilder builder = null;
		Document document = null;

		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			document = builder.parse(file);
			NodeList line_direction_nodes = document.getElementsByTagName("lineDirection");
			Node node0, child0;
			
			if (line_direction_nodes == null
					|| line_direction_nodes.getLength() != 1 ) {
				System.out.printf("Warning: line Direction in %s is not given%n", file);
				System.out.println("  The Line Direction is set to the defualt UNDEFINED");
			} else if( ! (line_direction_nodes.item(0).getNodeType() == Node.ELEMENT_NODE 
					&& line_direction_nodes.item(0).getChildNodes().getLength() == 1
					&& line_direction_nodes.item(0).getFirstChild().getNodeType() == Node.TEXT_NODE) ) {
				System.out.printf("Line Direction format in %s is illegal%n",file);
				System.out.println("  The Line Direction is set to the defualt UNDEFINED");
			} else {

				node0 = line_direction_nodes.item(0);

				if (node0 == null) {
					System.out.printf("Line Direction specification XML-element for %s is missing (1: for debugging)%n", file);
					System.out.println("The Line Direction is set the defualt UNDEFINED");
				} else	{

					child0 = node0.getFirstChild();

					if (child0 == null) {
						System.out.printf("Line Direction specification XML-element for %s has NULL-value (2: for debugging)%n", file);
						System.out.println("The Line Direction is set the defualt UNDEFINED");
					} else {

						String value0 = child0.getNodeValue();

						if (value0 == null) {
							System.out.printf("Line Direction specification for %s has  (3: for debugging)%n", file);
							System.out.println("The Line Direction is set the defualt UNDEFINED");
						} else {

							String directionString = value0.trim();

							if ( ! directionString.equalsIgnoreCase("horizontal") && ! directionString.equalsIgnoreCase("vertical")) {
								System.out.printf("Line Direction %s in %s is illegal%n", directionString, file);
							} else if (directionString.equalsIgnoreCase("horizontal")) {
								lineDirection = LineDirection.HORIZONTAL;
							} else if (directionString.equalsIgnoreCase("vertical")) {
								lineDirection = LineDirection.VERTICAL;
							}
						}
					}
				}
			}
			lines = document.getElementsByTagName("vertexes");
			for(int i=0;i<lines.getLength();i++){
				if(lines.item(i).getNodeType() == Node.ELEMENT_NODE){
					LineSegmentForEdit segment = this.getLineSegmentForEdit((Element)lines.item(i), i);
					results_lines.add(segment);
				}
			}
		} catch(ParserConfigurationException e){
			e.printStackTrace();
			return null;
		} catch (SAXException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
			//	e.printStackTrace();
		}
		return new Pair<LineDirection,List<LineSegmentForEdit>>(lineDirection,results_lines);
	}
	
	private LineSegmentForEdit getLineSegmentForEdit(Element element, int index){
		List<Point2D> points = new ArrayList<Point2D>();
		NodeList nodes = element.getElementsByTagName("vertex");
		double x = 0.0 ,y = 0.0;
		for(int i=0;i<nodes.getLength();i++){
			if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE){
				Element e = (Element)nodes.item(i);
				NodeList childs = e.getChildNodes();
				for(int j=0;j<childs.getLength();j++){
					if(childs.item(j).getNodeType() == Node.ELEMENT_NODE){
						Element elem = (Element)childs.item(j);
						if(elem.getNodeName().equals("x")){
							x = new Double(elem.getTextContent());
						}
						else if(elem.getNodeName().equals("y")){
							y = new Double(elem.getTextContent());
							points.add(new Point2D.Double(x,y));
						}
					}
				}
			}
		}
		return new LineSegmentForEdit(points,this.spread.getLineDirection(),index);
	}
}
