package com.ht.ui.monitor;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Popup;
import javafx.stage.Screen;
import javafx.util.StringConverter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ht.data.TagInfoManager;
import com.ht.tags.model.tag.TagVar;
import com.ht.ui.MainApplication;
import com.ht.ui.controls.ServiceProgressVeil;
import com.ht.ui.controls.calendar.FXCalendar;
import com.ht.ui.energy.ReportViewer;
import com.ht.ui.util.HessianResponseService;
import com.ht.ui.util.HessianResponseTask;
import com.ht.ui.util.MessageConstants;
import com.ht.web.hessian.HessianFactoryManger;
import com.ht.web.mongo.domain.YCHistoryData;
import com.ht.web.remoting.HessianResponse;

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

	private VBox mainPanel = new VBox(10);
//	private XYChart.Series<Number, Number> series;
	private NumberAxis xAxis;
	private LineChart<Number, Number> chart;
	private Map<String, XYChart.Series<Number, Number>> seriesMap = new HashMap<String, XYChart.Series<Number,Number>>();
	
	private FXCalendar fxCalendar;
	private Popup popup;

	private TextField textStart;
	private TextField textEnd;
	private TextField selText = null;
	
	private ReportViewer reportViewer;
	
	private Calendar calStart = Calendar.getInstance();
	private Calendar calEnd = Calendar.getInstance();

	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	
	private String[] tagVarName;
	private List<YCHistoryData> ycHistoryDataList;

	private HessianResponseService queryService = new HessianResponseService() {
		
		@Override
		protected Task<HessianResponse> createTask() {
			return new HessianResponseTask() {
				
				@Override
				protected HessianResponse call() throws Exception {
					try {
						return HessianFactoryManger.INSTANCE
								.getTagVarService().getTagVarHistoryData(
										tagVarName, calStart.getTime(),
										calEnd.getTime());
					} catch (Exception e) {
						e.printStackTrace();
					}
					return null;
				}
				
				@Override
				public void successResponse(HessianResponse resp) {
					if (resp.getData() != null) {
						ycHistoryDataList = (List<YCHistoryData>) resp
								.getData();
						for (YCHistoryData data : ycHistoryDataList) {

							XYChart.Series<Number, Number> series = seriesMap.get(data.getId().getVarName());
							if (series != null) {
								long l = data.getId().getDatetime().getTime();
								series.getData().add(
										new XYChart.Data<Number, Number>(l, data
												.getValue()));
							}
						}
					} else {
						showMessage(resp.getMsg());
						log.debug("返回数据为空, msg: {}", resp.getMsg());
					}
				}
				
				@Override
				public void nullResponse() {
					showMessage(MessageConstants.ERROR_APP_ERROR);
				}
				
				@Override
				public void failureResponse(HessianResponse resp) {
					showMessage(resp.getMsg());
				}
			};
		}
	};

	public HistoryLineChartViewer(final String title, final String ...tagVarName) {
		super();
		
		this.tagVarName = tagVarName;

		mainPanel.getStyleClass().addAll("window", "dataCurve", "monitor");
		mainPanel.setAlignment(Pos.TOP_CENTER);

		Rectangle2D rect = Screen.getPrimary().getVisualBounds();
		double maxHeight = rect.getHeight() - 270;
		double width = rect.getWidth() * 0.618;
		mainPanel.setPrefSize(width, maxHeight);
		mainPanel.setMaxSize(width, maxHeight);
		getChildren().add(mainPanel);

		// block mouse clicks
		setOnMouseClicked(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent t) {
				t.consume();
			}
		});

		createTopContent(title);
		createChart(title);
		
		queryData();

		// getChildren().add(fxCalendar);
	}

	private void createTopContent( final String title ) {
		
		calStart.set(Calendar.HOUR_OF_DAY, 0);
		calStart.set(Calendar.MINUTE, 0);
		calEnd.set(Calendar.HOUR_OF_DAY, 0);
		calEnd.set(Calendar.MINUTE, 1);

		Label titleLabel = new Label(title);
		titleLabel.getStyleClass().addAll("h3");
		mainPanel.getChildren().add(titleLabel);

		createPopup();

		HBox hbox = new HBox(5);
		hbox.setAlignment(Pos.CENTER_LEFT);
		hbox.getChildren().add(new Label(" 日期范围:"));

		textStart = new TextField();
		textStart.setPrefWidth(100);
		textStart.setEditable(false);
		textStart.setText( dateFormat.format(calStart.getTime()) );
		textStart.setOnMouseClicked(new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {

				selText = textStart;
				popup.show(textStart, event.getSceneX(), event.getSceneY());
			};
		});
		hbox.getChildren().add(textStart);

		Separator separator = new Separator(Orientation.HORIZONTAL);
		hbox.getChildren().add(separator);

		textEnd = new TextField();
		textEnd.setPrefWidth(100);
		textEnd.setEditable(false);
		textEnd.setText( dateFormat.format(calEnd.getTime()) );
		textEnd.setOnMouseClicked(new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {

				selText = textEnd;
				popup.show(textEnd, event.getSceneX(), event.getSceneY());
			};
		});
		hbox.getChildren().add(textEnd);

		Button showButton = new Button("查询");
		showButton.setPrefWidth(80);
		//showButton.setStyle("-fx-base: orange;");
		showButton.setOnAction(new EventHandler<ActionEvent>() {
			public void handle(ActionEvent event) {
				if (calStart.after(calEnd)) {
					showMessage("起始时间应该在结束时间之前");
					return;
				}

				xAxis.setTickUnit( (calStart.getTime().getTime() - calEnd.getTime().getTime()) / 12D);
				
				queryData();
			};
		});
		hbox.getChildren().add(showButton);
		
		
		final HessianResponseTask task = new HessianResponseTask() {
			
			@Override
			protected HessianResponse call() throws Exception {
				try {
					return HessianFactoryManger.INSTANCE.getReportService().ycHistory(title, calStart.getTime(), calEnd.getTime(), ycHistoryDataList);
				} catch (Exception e) {
					e.printStackTrace();
					log.error("应用程序错误 : {}", e);
				}
				return null;
			}
			
			@Override
			public void successResponse(HessianResponse resp) {
				if (reportViewer == null) {
					reportViewer = new ReportViewer();
				}
				MainApplication.getMainApp().showModalMessage(reportViewer);
				
				StringBuilder sb = new StringBuilder();
				sb.append("http://")
						.append(MainApplication.getMainApp().hostProperty().getValue())
						.append("/reports/show");
				sb.append(";jsessionid=").append(
						MainApplication.getCookieManager().getCookieStore()
								.getCookies().get(0).getValue());
				sb.append("?filename=yc_history.rptdesign");
				//System.out.println(sb2.toString());
				reportViewer.showHTML(sb.toString(), "yc_history.rptdesign");
			}
			
			@Override
			public void nullResponse() {
				showMessage("应用程序错误");
			}
			
			@Override
			public void failureResponse(HessianResponse resp) {
				showMessage(resp.getMsg());
			}
		};
		Button reportButton = new Button("报表");
		reportButton.setPrefWidth(80);
		reportButton.setOnAction(new EventHandler<ActionEvent>() {
			public void handle(ActionEvent event) {
				if (ycHistoryDataList != null) {
					task.start();
				}
			};
		});
		hbox.getChildren().add(reportButton);

		mainPanel.getChildren().add(hbox);
	}

	private void createPopup() {
		popup = new Popup();
		popup.setAutoHide(true);
		popup.setAutoFix(true);
		popup.setHideOnEscape(true);

		fxCalendar = new FXCalendar(false);
		fxCalendar.setOnDateSelected(new Runnable() {

			@Override
			public void run() {
				popup.hide();
				if (selText != null) {
					selText.setText(dateFormat.format(fxCalendar.getValue()));
					selText.setUserData(fxCalendar.getValue());

					if (selText.equals(textStart)) {
						calStart.setTime(fxCalendar.getValue());
						calStart.set(Calendar.HOUR_OF_DAY, 0);
						calStart.set(Calendar.MINUTE, 0);
					} else if (selText.equals(textEnd)) {
						calEnd.setTime(fxCalendar.getValue());
						calEnd.set(Calendar.HOUR_OF_DAY, 0);
						calEnd.set(Calendar.MINUTE, 1);
					}
					
					if (calStart.after(calEnd)) {
						showMessage("起始时间应该在结束时间之前");
					}
				}
			}
		});
		popup.getContent().add(fxCalendar);
	}

	private void createChart(final String title) {

		xAxis = new NumberAxis();
		//xAxis.setTickUnit(5);
		xAxis.setMinorTickVisible(false);
		xAxis.setAutoRanging(true);
		xAxis.setForceZeroInRange(false);
		xAxis.setTickLabelFormatter(new StringConverter<Number>() {

			private SimpleDateFormat sdf = new SimpleDateFormat("MM-dd\nHH:mm");

			@Override
			public Number fromString(String string) {
				return 20;
			}

			@Override
			public String toString(Number object) {
				// return object.toString();
				return sdf.format(new Date(object.longValue()));
			}
		});
		
		final NumberAxis yAxis = new NumberAxis();
		yAxis.setForceZeroInRange(false);
		yAxis.setAutoRanging(true);

		chart = new LineChart<Number, Number>(xAxis, yAxis);
		chart.setTitleSide(Side.RIGHT);
		chart.setMinHeight(mainPanel.getMaxHeight() * 0.9);
		chart.setCreateSymbols(false);
		chart.setLegendVisible(true);
		chart.setAnimated(false);
		// chart.setLegendVisible(false);

		// setup chart
		// chart.setTitle(title);
		// yAxis.setLabel("Y Axis");

		// xAxis.setLabel("X Axis");

		// add starting data
		for (String name : tagVarName) {
			XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
			
			Map<String, TagVar> tagVarNameMap = TagInfoManager.INSTANCE.getTagVarNameMap();
			if (tagVarNameMap != null) {
				
				TagVar tagVar = tagVarNameMap.get(name);
				if (tagVar == null) {
					series.setName(name);
				} else {
					series.setName(tagVar.getName());
				}
			} else {
				series.setName(name);
			}
			seriesMap.put(name, series);
			chart.getData().add(series);
		}
		//mainPanel.getChildren().add(chart);
		
//		ProgressIndicator progress = new ProgressIndicator();
//		progress.setMaxSize(150, 150);
//		Region veil = new Region();
//		veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
//		
//		StackPane stackPane = new StackPane();
//		VBox.setVgrow(stackPane, Priority.ALWAYS);
//		stackPane.getChildren().addAll(chart, veil, progress);
//		
//		progress.progressProperty().bind(queryService.progressProperty());
//        veil.visibleProperty().bind(queryService.runningProperty());
//        progress.visibleProperty().bind(queryService.runningProperty());
        
		mainPanel.getChildren().add(new ServiceProgressVeil(chart, queryService));
	}

	private void showMessage(String content) {
		MainApplication.getMainApp().showMessage(content);
	}

	private void queryData() {
		// 清空数据
		for (XYChart.Series<Number, Number> series : chart.getData()) {
			series.getData().clear();
		}
		
		queryService.restart();
	}

	public static void showWindow(final String title, final String ...tagVarName) {
		if (tagVarName.length == 0) {
			return;
		}
		Platform.runLater(new Runnable() {

			public void run() {
				MainApplication.getMainApp().showModalMessage(
						new HistoryLineChartViewer(title, tagVarName));
			}
		});
	}
}
