/* Copyright 2014 Malcolm Herring
 *
 * This 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, version 3 of the License.
 *
 * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
 */

package jicons;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.apache.batik.dom.GenericDOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;

import s57.S57map;
import s57.S57map.*;
import render.*;
import render.Rules.RuleSet;

public class Jicons {
	
	static int x = 0;
	static int y = 0;
	static int w = 0;
	static int h = 0;
	static double s = 0;

	public static void main(String[] args) throws IOException {
		Context context;
		S57map map = null;
		BufferedReader in;
		int line = 0;
		String format = "";
		String file = "";
		String k = "";
		String v = "";

		BufferedImage img;
		Graphics2D g2;
		boolean inIcons = false;
		boolean inIcon = false;
		
		if (args.length < 2) {
			System.err.println("Usage: java -jar jicons.jar icon_definition_file icons_directory");
			System.exit(-1);
		}
		in = new BufferedReader(new FileReader(args[0]));
		
		context = new Context();
		String ln;
		while ((ln = in.readLine()) != null) {
			line++;
			if (inIcons) {
				if (inIcon) {
					if (ln.contains("</icon")) {
						inIcon = false;
						map.tagsDone(0);
						// generate icon file
						switch (format) {
						case "PNG":
							img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
							g2 = img.createGraphics();
							Renderer.reRender(g2, RuleSet.SEAMARK, new Rectangle(x, y, w, h), 16, s / Renderer.symbolScale[16], map, context);
							try {
								ImageIO.write(img, "png", new File(args[1] + file + ".png"));
							} catch (Exception e) {
								System.err.println("Line " + line + ": PNG write Exception");
							}
							System.err.println(file + ".png");
							break;
						case "SVG":
							DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
							String svgNS = "http://www.w3.org/2000/svg";
							Document document = domImpl.createDocument(svgNS, "svg", null);
							SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
							svgGenerator.setSVGCanvasSize(new Dimension(w, h));
							Renderer.reRender(svgGenerator, RuleSet.SEAMARK, new Rectangle(x, y, w, h), 16, s / Renderer.symbolScale[16], map, context);
							boolean useCSS = true;
							Writer out = null;
							try {
								out = new OutputStreamWriter(new FileOutputStream(args[1] + file + ".svg"), "UTF-8");
							} catch (IOException e1) {
								System.err.println("Line " + line + ": SVG file Exception");
							}
							try {
								svgGenerator.stream(out, useCSS);
							} catch (SVGGraphics2DIOException e) {
								System.err.println("Line " + line + ": SVG write Exception");
							}
							System.err.println(file + ".svg");
							break;
						}
					} else if (ln.contains("<tag")) {
						k = v = "";
						String[] token = ln.split("k=");
						k = token[1].split("[\"\']")[1];
						token = token[1].split("v=");
						v = token[1].split("[\"\']")[1];
						if (k.isEmpty()) {
							System.err.println("Line " + line + ": No key in tag");
							System.exit(-1);
						}
						if (v.isEmpty()) {
							System.err.println("Line " + line + ": No value in tag");
							System.exit(-1);
						}
						map.addTag(k, v);
					}
				} else if (ln.contains("<icon")) {
					inIcon = true;
					h = w = x = y = -1;
					s = 0;
					file = format = "";
					map = new S57map(true);
					map.addNode(0, 0, 0);
					for (String token : ln.split("[ ]+")) {
						if (token.matches("^width=.+")) {
							w = Integer.parseInt(token.split("[\"\']")[1]);
						} else if (token.matches("^height=.+")) {
							h = Integer.parseInt(token.split("[\"\']")[1]);
						} else if (token.matches("^x=.+")) {
							x = Integer.parseInt(token.split("[\"\']")[1]);
						} else if (token.matches("^y=.+")) {
							y = Integer.parseInt(token.split("[\"\']")[1]);
						} else if (token.matches("^scale=.+")) {
							s = Double.parseDouble(token.split("[\"\']")[1]);
						} else if (token.matches("^file=.+")) {
							file = (token.split("[\"\']")[1]);
						} else if (token.matches("^format=.+")) {
							format = (token.split("[\"\']")[1]);
						}
					}
					if (file.isEmpty()) {
						System.err.println("Line " + line + ": No filename");
						System.exit(-1);
					}
					if (format.isEmpty()) {
						System.err.println("Line " + line + ": No format");
						System.exit(-1);
					}
					if ((h < 0) && (w < 0)) {
						System.err.println("Line " + line + ": No icon size");
						System.exit(-1);
					}
					if (w < 0) {
						w = h;
					}
					if (h < 0) {
						h = w;
					}
					if (x < 0) {
						x = w / 2;
					}
					if (y < 0) {
						y = h / 2;
					}
					if (s == 0) {
						s = 1;
					}
				} else if (ln.contains("</icons")) {
					inIcons = false;
					break;
				}
			} else if (ln.contains("<icons")) {
				inIcons = true;
			}
		}
		in.close();
		System.err.println("Finished");
		System.exit(0);
	}
	
	static class Context implements ChartContext {
		
		@Override
		public Point2D getPoint(Snode coord) {
			return new Point2D.Double(x, y);
		}

		@Override
		public double mile(Feature feature) {
			return Math.min(w, h);
		}

		@Override
		public boolean clip() {
			return false;
		}

		@Override
		public Color background() {
			return new Color(0, true);
		}
	}
}
