package com.ht.ui.monitor;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.TreeItem;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Screen;

import com.ht.data.RealTimeDataManager;
import com.ht.data.TagInfoManager;
import com.ht.data.listener.IDataListener;
import com.ht.tags.model.index.IndexTreeNode;
import com.ht.tags.model.tag.TagVar;
import com.ht.ui.MainApplication;
import com.ht.ui.controls.IndexNodeTreeItem;
import com.ht.ui.controls.ServiceProgressVeil;
import com.ht.ui.taginfo.MainIndexNodeTree;
import com.ht.util.WorkQueue;

public class TagVarMonitor extends BorderPane {

	private Map<String, IndexNodeTreeItem> indexTreeNodeMap = new HashMap<String, IndexNodeTreeItem>();

	private TagVarRealTimeDataTable table;

	private ToggleGroup group;

	private MainIndexNodeTree tree;

	private IDataListener dataListener;

	private ContextMenu contextMenu;
	private Service<ObservableList<TagVar>> filterService;

	public TagVarMonitor() {

		getStylesheets().add(
				getClass().getResource("TagVarMonitor.css").toExternalForm());
		setId("TagVarMonitor");

		getStyleClass().add("window");
		setMaxHeight(Screen.getPrimary().getVisualBounds()
				.getHeight() * 0.618);
		setMaxWidth(Screen.getPrimary().getVisualBounds().getWidth() - 40);
		
		setOnMouseClicked(new EventHandler<MouseEvent>() {

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

		parentProperty().addListener(new ChangeListener<Parent>() {
			@Override
			public void changed(ObservableValue<? extends Parent> observable,
					Parent oldValue, Parent newValue) {

				if (newValue != null) {

					filterService.restart();
				} else {
					if (dataListener != null) {
						WorkQueue.INSTANCE.execute(new Runnable() {
							public void run() {
								RealTimeDataManager.INSTANCE
										.unregistDataChangeListener(dataListener);
							}
						});
					}
				}
			}
		});

		createTop();
		createLeft();
		createCenter();

	}

	private void createCenter() {

		filterService = new Service<ObservableList<TagVar>>() {
			@Override
			protected Task<ObservableList<TagVar>> createTask() {
				return new Task<ObservableList<TagVar>>() {
					@Override
					protected ObservableList<TagVar> call() throws Exception {

						final IDataListener dataListener = TagVarMonitor.this.dataListener;
						if (dataListener != null) {
							WorkQueue.INSTANCE.execute(new Runnable() {
								public void run() {

									RealTimeDataManager.INSTANCE
											.unregistDataChangeListener(dataListener);
								}
							});
						}

						final String type = ((ToggleButton) group
								.getSelectedToggle()).getText();
						ObservableList<TagVar> list = FXCollections
								.observableArrayList();
						final Set<String> varNameSet = new HashSet<String>();

						if (TagInfoManager.INSTANCE.getTagVarNameMap() != null
								&& !tree.getSelectionModel().isEmpty()) {
							IndexTreeNode node = tree.getSelectionModel()
									.getSelectedItem().getValue();
							if (node != null) {

								String path = node.getPath() + "/";

								for (TagVar var : TagInfoManager.INSTANCE
										.getTagVarNameMap().values()) {
									if (var.getType().startsWith(type)) {
										if (var.getTagPath().startsWith(path)) {
											// table.getItems().add(var);
											list.add(var);
											varNameSet.add(var.getVarId());
										}
									}
								}
							}
						}
						if (!varNameSet.isEmpty()
								&& TagInfoManager.INSTANCE.getTagVarNameMap() != null) {

							final IDataListener listener = new IDataListener() {

								@Override
								public Set<String> getDataVarNames() {
									return varNameSet;
								}

								@Override
								public void dataChanged(String... varNames) {

									if (table != null) {
										for (String name : varNames) {
											final TagVar var = TagInfoManager.INSTANCE
													.getTagVarNameMap().get(
															name);
											final Object obj = RealTimeDataManager.INSTANCE
													.getVarValue(name);
											if (var != null && obj != null) {
												Platform.runLater(new Runnable() {
													public void run() {
														table.varDataValueChanged(
																var, obj);
													}
												});
											}
										}
									}
								}
							};
							TagVarMonitor.this.dataListener = listener;
							WorkQueue.INSTANCE.execute(new Runnable() {
								public void run() {

									RealTimeDataManager.INSTANCE
											.registDataChangeListener(listener);
									RealTimeDataManager.INSTANCE
											.updateVarValues(listener
													.getDataVarNames());
								}
							});
						}
						Collections.sort(list, new Comparator<TagVar>() {
							@Override
							public int compare(TagVar o1, TagVar o2) {
								return o1.getTagPath().compareTo(o2.getTagPath());
							}
						});
						return list;
					}
				};
			}
		};
		filterService.setExecutor(WorkQueue.INSTANCE.getThreadPool());
		
		table = new TagVarRealTimeDataTable();
		table.itemsProperty().bind(filterService.valueProperty());
//		mainPanel.setCenter(table);
		createContextMenu();

		ServiceProgressVeil veil = new ServiceProgressVeil(table, filterService);
		setCenter(veil);
	}

	private void createContextMenu() {
		contextMenu = new ContextMenu();

		MenuItem realTimeLineItem = new MenuItem("实时曲线");
		realTimeLineItem.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				// RealTimeLineChartViewer chartViewer = new
				// RealTimeLineChartViewer("",
				// table.getSelectionModel().getSelectedItem().getVarId(),
				// 2000);
				// getChildren().add(chartViewer);
				// RealTimeLineChartViewer.showWindow("", 2000,
				// table.getSelectionModel().getSelectedItem().getVarId());
				if (table.getSelectionModel().isEmpty()) {

					MainApplication.getMainApp().showMessage("请先选择一个变量");
				} else {

					String[] array = new String[table.getSelectionModel()
							.getSelectedItems().size()];
					int i = 0;
					for (TagVar var : table.getSelectionModel()
							.getSelectedItems()) {
						array[i] = var.getVarId();
						i++;
					}

					RealTimeLineChartViewer.showWindow(tree.getSelectionModel()
							.getSelectedItem().getValue().getPath(), 2000,
							array);
				}
			}
		});
		MenuItem historyLineItem = new MenuItem("负荷曲线");
		historyLineItem.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				if (table.getSelectionModel().isEmpty()) {

					MainApplication.getMainApp().showMessage("请先选择一个变量");
				} else {

					String[] array = new String[table.getSelectionModel()
							.getSelectedItems().size()];
					int i = 0;
					for (TagVar var : table.getSelectionModel()
							.getSelectedItems()) {
						array[i] = var.getVarId();
						i++;
					}

					HistoryLineChartViewer.showWindow(tree.getSelectionModel()
							.getSelectedItem().getValue().getPath()
							+ "负荷曲线", array);
				}
			}
		});

		contextMenu.getItems().addAll(realTimeLineItem, historyLineItem);
	}

	private void createLeft() {
		tree = new MainIndexNodeTree(indexTreeNodeMap,
				new TagVarTreeSelectedListener());
		tree.getSelectionModel().select(0);
		BorderPane.setMargin(tree, new Insets(0, 5, 0, 0));
		setLeft(tree);
	}

	private void createTop() {
		HBox hb = new HBox();
		hb.getStyleClass().add("ab-toggle");
		hb.setStyle("-fx-base: deepskyblue;");
		BorderPane.setMargin(hb, new Insets(0, 0, 5, 0));

		ToggleButton tb1 = new ToggleButton("遥信");
		ToggleButton tb2 = new ToggleButton("遥测");
		ToggleButton tb3 = new ToggleButton("遥脉");
		ToggleButton tb4 = new ToggleButton("遥控");
		ToggleButton tb5 = new ToggleButton("遥调");
		ToggleButton tb6 = new ToggleButton("内存变量");

		tb1.getStyleClass().add("left");
		tb6.getStyleClass().add("right");

		group = new ToggleGroup();
		tb1.setToggleGroup(group);
		tb2.setToggleGroup(group);
		tb3.setToggleGroup(group);
		tb4.setToggleGroup(group);
		tb5.setToggleGroup(group);
		tb6.setToggleGroup(group);
		group.selectToggle(tb1);
		// tb1.setDisable(true);

		group.selectedToggleProperty().addListener(
				new ChangeListener<Toggle>() {

					@Override
					public void changed(
							ObservableValue<? extends Toggle> observable,
							Toggle oldValue, Toggle selectedToggle) {
						if (selectedToggle != null) {
							if (oldValue != null
									&& !oldValue.equals(selectedToggle)) {
								if (filterService != null) {
									filterService.restart();
								}
								String type = ((ToggleButton) selectedToggle)
										.getText();
								if (type.equals("遥测") || type.equals("遥脉")) {

									table.setContextMenu(contextMenu);
								} else {
									table.setContextMenu(null);
								}
							}
						} else {
							group.selectToggle(oldValue);
						}
					}
				});

		hb.getChildren().addAll(tb1, tb2, tb3, tb4, tb5, tb6);
		setTop(hb);
	}

	/**
	 * 树选择监听器
	 * 
	 * @author Administrator
	 * 
	 */
	private class TagVarTreeSelectedListener implements
			ChangeListener<TreeItem<IndexTreeNode>> {

		@Override
		public void changed(
				ObservableValue<? extends TreeItem<IndexTreeNode>> observable,
				TreeItem<IndexTreeNode> oldValue,
				TreeItem<IndexTreeNode> newValue) {
			if (newValue != null) {
				if (filterService != null) {
					filterService.restart();
				}
			}
		}

	}
}
