/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ht.ui.energy;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.effect.Effect;
import javafx.scene.effect.SepiaTone;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import javafx.stage.Screen;
import javafx.util.Callback;
import javafx.util.StringConverter;

import org.javafxdata.control.cell.LabelCellFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ht.tags.model.index.IndexTreeNode;
import com.ht.tags.model.index.IndexType;
import com.ht.ui.MainApplication;
import com.ht.ui.chart.AdvCmpChart;
import com.ht.ui.chart.AdvCmpChart.AdvCmpChartExtraValues;
import com.ht.ui.controls.calendar.FXCalendar;
import com.ht.ui.controls.cell.NumberCellFactory;
import com.ht.ui.energy.util.EnergyConverterUtil;
import com.ht.ui.user.UserLoginDialog;
import com.ht.ui.util.HessianResponseTask;
import com.ht.ui.util.MessageConstants;
import com.ht.ui.util.UserSecurityUtil;
import com.ht.util.DateType;
import com.ht.util.UserSession;
import com.ht.web.hessian.HessianFactoryManger;
import com.ht.web.mongo.domain.EnergyStatisticData;
import com.ht.web.mongo.domain.User;
import com.ht.web.remoting.HessianResponse;

/**
 * 统计汇总视图
 * 
 * @author Administrator
 */
public class EnergyCmpView extends HBox {

	private static final Logger log = LoggerFactory
			.getLogger(EnergyCmpView.class);

	private ReportViewer reportViewer;

	private Date date = new Date();
	private DateType dateType = DateType.DAILY;

	private IndexTreeNode energyIndexNode;
	private Map<String, IndexTreeNode> normalIndexMap = new HashMap<String, IndexTreeNode>();

	private SimpleDateFormat dailyDateFormat = new SimpleDateFormat(
			"yyyy年MM月dd日");
	private SimpleDateFormat monthlyDateFormat = new SimpleDateFormat(
			"yyyy年MM月");
	private SimpleDateFormat yearlyDateFormat = new SimpleDateFormat("yyyy年");

	private SimpleDateFormat dailyDF = new SimpleDateFormat("HH:00");
	private SimpleDateFormat monthlyDF = new SimpleDateFormat("MM月dd日");
	private SimpleDateFormat yearlyDF = new SimpleDateFormat("yyyy年MM月");

	private TableView<EnergyCmpData> energyDataTable;
	private ObservableList<EnergyCmpData> energyDataList = FXCollections
			.observableArrayList();

	private TableColumn<EnergyCmpData, Number> valueCol;

	private AdvCmpChart<String, Number> chart;

	private Effect lastEffect;

	private XYChart.Series<String, Number> series;
	private CategoryAxis xAxis;
	private NumberAxis yAxis;
	private EnergyManageView parentView;

	private TableColumn<EnergyCmpData, String> dateTimeCol;

	public EnergyCmpView(EnergyManageView parent,
			IndexTreeNode energyIndexNode,
			Map<String, IndexTreeNode> normalIndexMap) {
		super(20);
		setId("EnergyCmpView");
		setAlignment(Pos.TOP_CENTER);

		this.parentView = parent;

		createMiddle();
		createRight();
		configureDrag();

		this.energyIndexNode = energyIndexNode;
		this.normalIndexMap.putAll(normalIndexMap);

		if (energyIndexNode != null && !normalIndexMap.isEmpty()) {
			updateChart();
		}
	}

	public synchronized void showReportViewer() {
		if (normalIndexMap.isEmpty()) {
			log.debug("未选择建筑名称");
			return;
		}

		if (energyIndexNode == null) {

			log.debug("未选择能耗分类或分项");
			return;
		}

		if (reportViewer == null) {
			reportViewer = new ReportViewer();
		}

		try {

			List<String> normalList = new ArrayList<String>(
					normalIndexMap.size());
			for (IndexTreeNode node : normalIndexMap.values()) {
				normalList.add(node.getPath());
			}

			HessianResponse resp = HessianFactoryManger.INSTANCE
					.getReportService().tongBi(dateType, "", date, normalList,
							energyIndexNode.getPath());

			if (resp != null && resp.isSuccessful()) {

				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=tongbi_");
				sb.append(dateType.toString().toLowerCase()).append(
						".rptdesign");
				
				String reportFileName = "tongbi_" + dateType.toString().toLowerCase() + ".rptdesign";
				reportViewer.showHTML(sb.toString(), reportFileName);
			} else {
				MainApplication.getMainApp().showMessage("服务器未响应");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void createMiddle() {

		VBox vb = new VBox();
		vb.getStyleClass().add("window");

		Rectangle2D rect = Screen.getPrimary().getVisualBounds();
		double height = rect.getHeight() - 130;
		double width = rect.getWidth() - 180;
		vb.setPrefWidth(width);

		createChart();
		chart.setPrefHeight(height);

		energyDataTable = createTable();

		vb.getChildren().addAll(createTop(), chart, energyDataTable);

		getChildren().add(vb);
	}

	private Node createTop() {
		HBox hbox = new HBox(5);
		hbox.setPadding(new Insets(0, 20, 0, 20));

		Button clearBtn = new Button("重置");
		clearBtn.setPrefWidth(80);
		clearBtn.setStyle("-fx-base: lightblue;");
		clearBtn.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent arg0) {
				// MainChartViewer.this.parentViewer.clearData();
			}
		});

		Button reportBtn = new Button("报表");
		reportBtn.setPrefWidth(80);
		reportBtn.setStyle("-fx-base: lightblue;");
		reportBtn.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				// parentViewer.showReportViewer();
			}
		});

		hbox.getChildren().addAll(clearBtn, reportBtn);

		return hbox;
	}

	private TableView<EnergyCmpData> createTable() {
		TableView<EnergyCmpData> table = new TableView<EnergyCmpData>();
		table.setPrefHeight(500);

		DecimalFormat decimalFormat = new DecimalFormat("0.0#");
		Callback<TableColumn<EnergyCmpData, Number>, TableCell<EnergyCmpData, Number>> valueCellCallback = LabelCellFactory
				.<EnergyCmpData, Number> forTableColumn(TextAlignment.RIGHT,
						decimalFormat);

		DecimalFormat rateDF = new DecimalFormat("#0.##%");
		rateDF.setPositivePrefix("+");
		Callback<TableColumn<EnergyCmpData, Number>, TableCell<EnergyCmpData, Number>> valueRateCellCallback = NumberCellFactory
				.<EnergyCmpData, Number> forTableColumn(rateDF);

		dateTimeCol = new TableColumn<EnergyCmpView.EnergyCmpData, String>(
				"日期/时间");
		dateTimeCol.setPrefWidth(100);
		dateTimeCol
				.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, String>, ObservableValue<String>>() {

					@Override
					public ObservableValue<String> call(
							CellDataFeatures<EnergyCmpData, String> param) {
						return param.getValue().getDate();
					}
				});
		// dateTimeCol.setCellFactory(LabelCellFactory
		// .<EnergyCmpData, Date> forTableColumn(timeDF));
		table.getColumns().add(dateTimeCol);

		valueCol = new TableColumn<EnergyCmpView.EnergyCmpData, Number>(
				"每小时能耗量(kWh)");
		valueCol.setPrefWidth(130);
		valueCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, Number>, ObservableValue<Number>>() {

			@Override
			public ObservableValue<Number> call(
					CellDataFeatures<EnergyCmpData, Number> param) {
				return param.getValue().getValue();
			}
		});
		valueCol.setCellFactory(valueCellCallback);
		table.getColumns().add(valueCol);

		TableColumn<EnergyCmpData, Number> yearValueCol = new TableColumn<EnergyCmpView.EnergyCmpData, Number>(
				"同比能耗");
		yearValueCol.setPrefWidth(120);
		yearValueCol
				.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, Number>, ObservableValue<Number>>() {

					@Override
					public ObservableValue<Number> call(
							CellDataFeatures<EnergyCmpData, Number> param) {
						return param.getValue().getYearValue();
					}
				});
		yearValueCol.setCellFactory(valueCellCallback);
		table.getColumns().add(yearValueCol);

		TableColumn<EnergyCmpData, Number> yearRateCol = new TableColumn<EnergyCmpView.EnergyCmpData, Number>(
				"同比增长率");
		yearRateCol.setPrefWidth(120);
		yearRateCol
				.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, Number>, ObservableValue<Number>>() {

					@Override
					public ObservableValue<Number> call(
							CellDataFeatures<EnergyCmpData, Number> param) {
						return param.getValue().getYearRate();
					}
				});
		yearRateCol.setCellFactory(valueRateCellCallback);

		table.getColumns().add(yearRateCol);

		TableColumn<EnergyCmpData, Number> linkValueCol = new TableColumn<EnergyCmpView.EnergyCmpData, Number>(
				"环比能耗");
		linkValueCol.setPrefWidth(120);
		linkValueCol
				.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, Number>, ObservableValue<Number>>() {

					@Override
					public ObservableValue<Number> call(
							CellDataFeatures<EnergyCmpData, Number> param) {
						return param.getValue().getLinkValue();
					}
				});
		linkValueCol.setCellFactory(valueCellCallback);
		table.getColumns().add(linkValueCol);

		TableColumn<EnergyCmpData, Number> linkRateCol = new TableColumn<EnergyCmpView.EnergyCmpData, Number>(
				"环比增长率");
		linkRateCol.setPrefWidth(120);
		linkRateCol
				.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EnergyCmpData, Number>, ObservableValue<Number>>() {
					@Override
					public ObservableValue<Number> call(
							CellDataFeatures<EnergyCmpData, Number> param) {
						return param.getValue().getLinkRate();
					}
					// @Override
					// public ObservableValue<Double> call(
					// CellDataFeatures<EnergyCmpData, Double> param) {
					// return param.getValue().getLinkRate();
					// }
				});
		linkRateCol.setCellFactory(valueRateCellCallback);
		table.getColumns().add(linkRateCol);

		table.setItems(energyDataList);

		return table;
	}

	@SuppressWarnings("unchecked")
	private void createChart() {

		xAxis = new CategoryAxis();

		yAxis = new NumberAxis();
		yAxis.setMinorTickCount(0);
		yAxis.setMinorTickVisible(false);
		yAxis.setAutoRanging(false);
		yAxis.setPrefWidth(80);
		// yAxis.setUpperBound(60);
		yAxis.setTickLabelFormatter(new StringConverter<Number>() {

			private DecimalFormat df = new DecimalFormat("#0");

			@Override
			public Number fromString(String string) {
				return Double.parseDouble(string);
			}

			@Override
			public String toString(Number object) {
				return df.format(object.doubleValue());
			}
		});

		chart = new AdvCmpChart<String, Number>(xAxis, yAxis);
		chart.setAlignTotick(false);
		// chart.setTitle("2012年2月电能耗对比");
		// xAxis.setLabel("日期时间");
		// yAxis.setLabel("能耗值");
		// add starting data

		series = new XYChart.Series<String, Number>();
		series.setName("能耗值");

		// for (int i = 0; i < data.length; i++) {
		// double[] day = data[i];
		// series.getData().add(
		// new XYChart.Data<Number, Number>(day[0], day[1],
		// new AdvCmpChartExtraValues(day[2], day[3])));
		// }
		chart.setData(FXCollections.observableArrayList(series));
	}

	private void configureDrag() {
		final DataFormat dragContentKey = new DataFormat("data");
		this.setOnDragOver(new EventHandler<DragEvent>() {

			@Override
			public void handle(DragEvent event) {
				if (event.getDragboard().hasContent(dragContentKey)) {
					event.acceptTransferModes(TransferMode.MOVE);
				}

				event.consume();
			}
		});

		final SepiaTone sepiaTone = new SepiaTone();
		sepiaTone.setLevel(0.2d);
		this.setOnDragEntered(new EventHandler<DragEvent>() {

			@Override
			public void handle(DragEvent event) {
				if (event.getDragboard().hasContent(dragContentKey)) {
					System.out.println(event.getTarget());
					lastEffect = getEffect();
					setEffect(sepiaTone);
				}

				event.consume();
			}
		});
		this.setOnDragExited(new EventHandler<DragEvent>() {

			@Override
			public void handle(DragEvent event) {
				setEffect(lastEffect);
				event.consume();
			}
		});

		this.setOnDragDropped(new EventHandler<DragEvent>() {

			@Override
			public void handle(DragEvent event) {
				Dragboard db = event.getDragboard();
				boolean success = false;
				if (db.hasContent(dragContentKey)) {
					IndexTreeNode node = (IndexTreeNode) db
							.getContent(dragContentKey);
					addIndexPath(node);

					success = true;
				}
				event.setDropCompleted(success);

				event.consume();
			}
		});
	}

	public DateType getDateType() {
		return dateType;
	}

	private void updateChartTitle() {
		String prefix = "";
		switch (dateType) {
		case DAILY:
			prefix = dailyDateFormat.format(date);
			break;
		case MONTHLY:
			prefix = monthlyDateFormat.format(date);
			break;
		case YEARLY:
			prefix = yearlyDateFormat.format(date);
			break;
		default:
			break;
		}

		StringBuilder sb = new StringBuilder();

		sb.append(prefix).append(" ");
		for (Entry<String, IndexTreeNode> entry : normalIndexMap.entrySet()) {
			sb.append(entry.getValue().getName());
		}
		sb.append(" ");
		// sb.append(" ").append(energyIndexNode.getIndexName()).append("使用量");//
		// 能耗分类
		// if (energyIndexNode.getPath().contains("/")) {
		// // 能耗分项
		// sb.append("(").append(energyIndexNode.getName()).append(")");
		// }
		if (energyIndexNode.getPath().contains("/")) {// 能耗分项
			sb.append(energyIndexNode.getName());
		} else {
			sb.append(EnergyConverterUtil.getEnergyTitle(energyIndexNode
					.getIndexName()));// 能耗分类
		}
		sb.append(" 同比环比分析");

		chart.setTitle(sb.toString());

		sb = new StringBuilder();
		sb.append(energyIndexNode.getName()).append("能耗");
		sb.append("(")
				.append(EnergyConverterUtil.getEnergyUnit(energyIndexNode
						.getPath())).append(")");
		series.setName(sb.toString());

		yAxis.setLabel(sb.toString());
	}

	private void updateTableHeaderTitle() {
		String prefix = "";
		switch (dateType) {
		case DAILY:
			prefix = "每小时";
			break;
		case MONTHLY:
			prefix = "日";
			break;
		case YEARLY:
			prefix = "月";
			break;
		default:
			break;
		}

		if (energyIndexNode != null) {
			StringBuilder sb = new StringBuilder(prefix)
					.append("能耗量(")
					.append(EnergyConverterUtil.getEnergyUnit(energyIndexNode
							.getPath())).append(")");
			valueCol.setText(sb.toString());
		}
	}

	private void createRight() {
		final FXCalendar fxCalendar = new FXCalendar();
		fxCalendar.setStyle("-fx-font-size:14px;");
		fxCalendar.setTranslateY(-50);
		fxCalendar.setOnDateSelected(new Runnable() {

			@Override
			public void run() {
				date = fxCalendar.getValue();
				energyDataList.clear();
				dateType = fxCalendar.getDateTypeButton().getDateType();

				// switch (dateType) {
				// case DAILY:
				// dateTimeCol.setCellFactory(LabelCellFactory.<EnergyCmpData,
				// Date> forTableColumn(dailyDF));
				// break;
				// case MONTHLY:
				// dateTimeCol.setCellFactory(LabelCellFactory.<EnergyCmpData,
				// Date> forTableColumn(monthlyDF));
				// break;
				// case YEARLY:
				// dateTimeCol.setCellFactory(LabelCellFactory.<EnergyCmpData,
				// Date> forTableColumn(yearlyDF));
				// break;
				// default:
				// break;
				// }

				updateTableHeaderTitle();

				updateChart();
			}
		});

		Region spacer = new Region();
		VBox.setVgrow(spacer, Priority.ALWAYS);

		VBox vb = new VBox();
		vb.setSpacing(20);
		vb.getChildren().addAll(spacer, fxCalendar);
		fxCalendar.toFront();
		getChildren().add(vb);
	}

	/**
	 * 清除数据
	 */
	public void clearData() {
		energyIndexNode = null;
		normalIndexMap.clear();

		energyDataList.clear();
		for (Object obj : energyDataTable.getProperties().values()) {
			energyDataTable.getColumns().remove(obj);
		}
	}

	public void addIndexPath(final IndexTreeNode indexNode) {
		log.debug("添加分项: {}, {}", indexNode.getIndexName(), indexNode.getPath());
		if (indexNode.getIndexType().equals(IndexType.ENERGY)) {// 能耗分项
			this.energyIndexNode = indexNode;
			updateTableHeaderTitle();
		} else {// 常规分类条件
			normalIndexMap.put(indexNode.getIndexName(), indexNode);
		}

		if (energyIndexNode != null && normalIndexMap.size() > 0) {
			updateChart();
		}

	}

	public void updateChart() {
		updateChartTitle();

		log.debug("计算统计数据");
		User user = UserSession.INSTANCE.getUser();
		if (user == null) {

			UserLoginDialog.getInstance().showDialog(new Runnable() {

				@Override
				public void run() {
					updateChart();
				}
			}, "您已自动退出, 请重新登录.");
		} else if (!user.getGroup().getEnergyStatistic()) {

			// mainChartViewer.showMessage("您没有权限执行该操作, 请重新登录.");
			UserLoginDialog.getInstance().showDialog(new Runnable() {

				@Override
				public void run() {
					updateChart();
				}
			}, "您没有权限执行该操作, 请以另一个账号登录.");
		}

		if (energyIndexNode == null) {
			// mainChartViewer.showMessage("请选择一项能耗分项");
			return;
		} else if (normalIndexMap.isEmpty()) {
			// mainChartViewer.showMessage("请选择一项常规分类");
			return;
			// } else {

		}

		List<String> normalIndexList = new ArrayList<String>();
		for (IndexTreeNode node : normalIndexMap.values()) {
			normalIndexList.add(node.getPath());
		}
		handleData(normalIndexList);
	}

	@SuppressWarnings("unchecked")
	private void handleData(final List<String> normalIndexList) {
		UserSecurityUtil.verifyUserAuthority(new Runnable() {

			@Override
			public void run() {
				User user = UserSession.INSTANCE.getUser();
				if (!user.getGroup().getEnergyStatistic()) {
					return;
				}

				new HessianResponseTask() {

					@Override
					protected HessianResponse call() throws Exception {
						try {

							return HessianFactoryManger.INSTANCE
									.getTagVarService().getYMStatisticData(
											dateType,
											energyIndexNode.getPath(),
											normalIndexList, date);
						} catch (Exception e) {
							e.printStackTrace();
						}
						return null;
					}

					@Override
					public void successResponse(HessianResponse resp) {
						Comparator<EnergyStatisticData> comparator = new Comparator<EnergyStatisticData>() {
							@Override
							public int compare(EnergyStatisticData o1,
									EnergyStatisticData o2) {
								return o1.getValue().getDatetime()
										.compareTo(o2.getValue().getDatetime());
							}
						};

						// 本期数据
						List<EnergyStatisticData> currentData = (List<EnergyStatisticData>) resp
								.getData();
						Collections.sort(currentData, comparator);

						Calendar cal = Calendar.getInstance();
						cal.setTime(date);
						cal.add(Calendar.YEAR, -1);
						try {
							resp = HessianFactoryManger.INSTANCE
									.getTagVarService().getYMStatisticData(
											dateType,
											energyIndexNode.getPath(),
											normalIndexList, cal.getTime());
							// 去年同期
							List<EnergyStatisticData> yearData = (List<EnergyStatisticData>) resp
									.getData();
							Collections.sort(yearData, comparator);

							parseResponse(currentData, yearData);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}

					@Override
					public void nullResponse() {
						parentView
								.showMessage(MessageConstants.ERROR_APP_ERROR);
					}

					@Override
					public void failureResponse(HessianResponse resp) {
						parentView.showMessage(resp.getMsg());
					}
				}.start();
			}
		});

	}

	private void parseResponse(List<EnergyStatisticData> currentData,
			List<EnergyStatisticData> yearData) {

		if (currentData.isEmpty()) {
			parentView.showMessage("未查询到符合条件的数据!");
			return;
		}

		series.getData().clear();
		energyDataList.clear();

		Map<String, Double> yearDataMap = new HashMap<String, Double>();

		for (EnergyStatisticData d : yearData) {

			String label = "";
			switch (dateType) {
			case DAILY:
				label = dailyDF.format(d.getValue().getDatetime());
				break;
			case MONTHLY:
				label = monthlyDF.format(d.getValue().getDatetime());
				break;
			case YEARLY:
				label = yearlyDF.format(d.getValue().getDatetime());
				break;
			default:
				break;
			}
			yearDataMap.put(label, d.getValue().getValue().doubleValue());
		}

		List<XYChart.Data<String, Number>> list = new ArrayList<XYChart.Data<String, Number>>();

		double maxValue = -1;
		// double maxId = -1;
		for (int i = 0; i < currentData.size(); i++) {
			EnergyStatisticData obj = currentData.get(i);

			String label = "";

			switch (dateType) {
			case DAILY:
				label = dailyDF.format(obj.getValue().getDatetime());
				break;
			case MONTHLY:
				label = monthlyDF.format(obj.getValue().getDatetime());
				break;
			case YEARLY:
				label = yearlyDF.format(obj.getValue().getDatetime());
				break;
			default:
				break;
			}

			// 本期数据
			double value = obj.getValue().getValue().doubleValue();
			// 前期数据
			double linkValue = (i == 0) ? value : currentData.get(i - 1)
					.getValue().getValue().doubleValue();
			// 同期数据, 如果没有同期数据，默认同期数据与本期数据相同
			double yearValue = yearDataMap.containsKey(label) ? yearDataMap
					.get(label) : Double.NaN;

			list.add(new XYChart.Data<String, Number>(label, value,
					new AdvCmpChartExtraValues(yearValue, linkValue)));

			if (value > maxValue) {
				maxValue = value;
			}
			// if (obj.getId() > maxId) {
			// maxId = obj.getId();
			// }

			EnergyCmpData energyData = new EnergyCmpData();

			// 设置分类分项属性
			energyData.getEnergyCategory().setValue(energyIndexNode.getName());
			for (Entry<String, IndexTreeNode> entry : normalIndexMap.entrySet()) {
				energyData.getNormalCategoryMap().put(entry.getKey(),
						new SimpleStringProperty(entry.getValue().getName()));
			}

			energyData.getDate().set(label);// 时间
			energyData.getValue().set(value);// 能耗值
			energyData.getYearValue().set(Double.isNaN(yearValue) ? 0 : yearValue);// 同比能耗
			energyData.getLinkValue().set(Double.isNaN(linkValue) ? 0 : linkValue);// 环比能耗
			if (value == 0) {
				energyData.getYearRate().set(Double.isNaN(yearValue) ? 0 : ( yearValue == 0 ? 0 : -1 ));
				energyData.getLinkRate().set(Double.isNaN(linkValue) ? 0 : ( linkValue == 0 ? 0 : -1 ));
			} else {
				energyData.getYearRate().set(Double.isNaN(yearValue) ? 0 : ( (value - yearValue) / value ));// 同比增长率
				energyData.getLinkRate().set(Double.isNaN(linkValue) ? 0 : ( (value - linkValue) / value ));// 环比增长率
			}

			energyDataList.add(energyData);
		}

		// xAxis.setUpperBound(maxId + 1);
		yAxis.setTickUnit(maxValue / 10);
		yAxis.setUpperBound(maxValue * 2);
		series.getData().addAll(list);

	}

	public static class EnergyCmpData {
		private StringProperty energyCategory = new SimpleStringProperty();
		private Map<String, StringProperty> normalCategoryMap = new HashMap<String, StringProperty>();
		private Map<Integer, DoubleProperty> itemMap = new HashMap<Integer, DoubleProperty>();

		private StringProperty date = new SimpleStringProperty();
		private DoubleProperty value = new SimpleDoubleProperty();

		private DoubleProperty yearValue = new SimpleDoubleProperty();
		private DoubleProperty yearRate = new SimpleDoubleProperty();

		private DoubleProperty linkValue = new SimpleDoubleProperty();
		private DoubleProperty linkRate = new SimpleDoubleProperty();

		public EnergyCmpData() {
		}

		public StringProperty getEnergyCategory() {
			return energyCategory;
		}

		public Map<String, StringProperty> getNormalCategoryMap() {
			return normalCategoryMap;
		}

		public Map<Integer, DoubleProperty> getItemMap() {
			return itemMap;
		}

		public StringProperty getDate() {
			return date;
		}

		public DoubleProperty getValue() {
			return value;
		}

		public DoubleProperty getYearValue() {
			return yearValue;
		}

		public DoubleProperty getYearRate() {
			return yearRate;
		}

		public DoubleProperty getLinkValue() {
			return linkValue;
		}

		public DoubleProperty getLinkRate() {
			return linkRate;
		}

	}
}
