package com.ht.ui.svg;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Screen;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import com.ht.data.RealTimeDataManager;
import com.ht.svg.action.ActionsHandler;
import com.ht.svg.animat.AnimatHandler;
import com.ht.svg.view.SvgViewModel;
import com.ht.ui.MainApplication;
import com.ht.util.WorkQueue;
import com.ht.web.hessian.HessianFactoryManger;

public class SVGViewer extends Group {
	private static final Logger log = LoggerFactory.getLogger(SVGViewer.class);

	private WebView webView = new WebView();
	private WebEngine webEngine = webView.getEngine();

	private AnimatHandler animateHandler;
	private ActionsHandler actionHandler;

	private double vbWidth;//
	private double vbHeight;
	private double vbX = 0;// svg viewbox x
	private double vbY = 0;// svg viewbox y
	
	private double svgScale = 1;
	
	private double svgHeight;// 实际像素大小
	private double svgWidth;// 实际像素大小
	
	private final double moveUnit = 30;



	public SVGViewer() {
		super();

		webView.setVisible(false);
		configureHandler();
		webView.setMinSize(3000, 3000);

		getChildren().addAll(webView);

	}

	/**
	 * 缩小
	 */
	public void zoomOut() {
		svgScale *= 1.1;
		zoom();
	}

	public void zoomIn() {
		svgScale /= 1.1;
		zoom();
	}

	public void zoomReset() {
		svgScale = 1;
		zoom();
	}
	
	public void moveReset() {
		vbX = 0;
		vbY = 0;
		zoom();
	}
	
	public void moveTop() {
		if (vbY + moveUnit > vbHeight * svgScale) {
			return;
		}
		vbY += moveUnit;
		zoom();
	}

	public void moveBottom() {
		if (vbY - moveUnit < -vbHeight * svgScale) {
			return;
		}
		vbY -= moveUnit;
		zoom();
	}

	public void moveLeft() {
		if (vbX + moveUnit > vbWidth * svgScale) {
			return;
		}
		vbX += moveUnit;
		zoom();
	}

	public void moveRight() {
		if (vbX - moveUnit < -vbWidth * svgScale) {
			return;
		}
		vbX -= moveUnit;
		zoom();
	}
	
	public void reset() {
		svgScale = 1;
		vbX = 0;
		vbY = 0;
		zoom();
	}

	private void zoom() {

		// String[] array = webEngine.getDocument().getDocumentElement()
		// .getAttribute("viewBox").split("\\s");

		String viewBoxX = Double.toString(vbX * svgScale);
		String viewBoxY = Double.toString(vbY * svgScale);
		String viewBoxWidth = Double.toString(vbWidth * svgScale);
		String viewBoxHeight = Double.toString(vbHeight * svgScale);

		String s = viewBoxX + " " + viewBoxY + " " + viewBoxWidth + " "
				+ viewBoxHeight;
		webEngine.getDocument().getDocumentElement().setAttribute("viewBox", s);
	}

	public void load(SvgViewModel view) {
		if (view.getFileName().toLowerCase().endsWith(".svgz")) {// .svgz
			InputStream is = null;
			try {
				is = HessianFactoryManger.INSTANCE.getSvgService().download(
						view.getFileName());

				if (is == null) {

				} else {

					GZIPInputStream gis = new GZIPInputStream(is);

					StringBuilder sb = new StringBuilder();

					int len = 0;
					byte[] buf = new byte[512];
					while ((len = gis.read(buf)) != -1) {
						sb.append(new String(buf, 0, len));
					}

					webEngine.loadContent(sb.toString(), "image/svg+xml");
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}

		} else {// .svg

			String url = "http://"
					+ MainApplication.getMainApp().hostProperty().getValue()
					+ "/" + view.getFileName();
			log.debug("显示svg视图：{}", url);
			webView.setVisible(false);
			webEngine.load(url);
		}
	}

	private void configureHandler() {

		webEngine.documentProperty().addListener(
				new ChangeListener<Document>() {

					@Override
					public void changed(
							ObservableValue<? extends Document> observable,
							Document oldValue, Document newValue) {
						if (animateHandler != null) {
							animateHandler.unregist();
							animateHandler.dispose();
							animateHandler = null;
						}
						if (actionHandler != null) {
							actionHandler.unregist();
							actionHandler.dispose();
							actionHandler = null;
						}

						if (newValue != null) {

							handleNewDocument(newValue);

							MainApplication.getMainApp().showDefaultView();

							// 注册新的动画处理类
							animateHandler = new AnimatHandler(SVGViewer.this,
									newValue);
							actionHandler = new ActionsHandler(SVGViewer.this,
									newValue);

							WorkQueue.INSTANCE.execute(new Runnable() {
								public void run() {

									animateHandler.init();
									actionHandler.init();

									RealTimeDataManager.INSTANCE
											.updateAllVarValues();
								}
							});

							webView.setVisible(true);
						}
					}
				});
	}

	private void handleNewDocument(Document doc) {
		String w = doc.getDocumentElement().getAttribute("width");
		String h = doc.getDocumentElement().getAttribute("height");
		if (w.isEmpty() || h.isEmpty()) {
			log.warn("svg document 未设置width或height属性");
			return;
		}

		double width = Double.parseDouble(w);
		double height = Double.parseDouble(h);

		// if (webView.getMinWidth() < svgWidth) {
		// webView.setMinWidth(svgWidth);
		// }
		//
		// if (webView.getMinHeight() < svgHeight) {
		// webView.setMinHeight(svgHeight);
		// }

		Rectangle2D bounds = Screen.getPrimary().getVisualBounds();

		String[] array = webEngine.getDocument().getDocumentElement()
				.getAttribute("viewBox").split("\\s");
		vbWidth = Double.parseDouble(array[2].trim());
		vbHeight = Double.parseDouble(array[3].trim());

		svgHeight = bounds.getHeight();
		svgWidth = svgHeight * width / height;

		webEngine.getDocument().getDocumentElement()
				.setAttribute("width", Double.toString(svgWidth));
		webEngine.getDocument().getDocumentElement()
				.setAttribute("height", Double.toString(svgHeight));

	}

	public AnimatHandler getAnimateHandler() {
		return animateHandler;
	}

	public ActionsHandler getActionHandler() {
		return actionHandler;
	}

	public WebEngine getWebEngine() {
		return webEngine;
	}

	public void blinkingReset() {
		if (animateHandler != null) {
			animateHandler.blinkingReset();
		}

	}

	public void dispose() {
		if (animateHandler != null) {
			animateHandler.dispose();
		}
		if (actionHandler != null) {
			actionHandler.dispose();
		}
	}
}
