/*
 * Created on 2007/03/12
 *
 *
 * Copyright(c) 2007 Yoshimasa Matsumoto
 */
package netjfwatcher.nodemap.gui;

import java.util.ArrayList;

import netjfwatcher.application.NetJFWatcherPlugin;
import netjfwatcher.engine.nodemaneger.map.NodeMapInfo;
import netjfwatcher.engine.socket.info.NodeInformation;
import netjfwatcher.engine.socket.info.NodeMapLinkInformation;
import netjfwatcher.engine.view.canvas.CanvasViewConfigFileParse;
import netjfwatcher.engine.view.editorpart.common.AbstractEditorNodeChart;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.osgi.framework.Bundle;

/**
 * ノードMap ViewにノードMapを描画するクラスです。
 * 
 * @author Yoshimasa Matsumoto
 * @version 1.0
 */
public class NodeMapDrawViewDraw {
	/* 配色Color定義 */
	private static Color WHITE_COLOR;

	private static Color BLACK_COLOR;

	private static Color RED_COLOR;

	private static Color TEST_COLOR;

	private static final int NODE_NAME_Y_OFFSET = 40;

	private static final int NODE_IPADDRESS_Y_OFFSET = 60;

	private static final int NODE_OVAL_VIEW_OFFSET = 3;
	
	/* ノードIconリンクを描画するIconオフセット値 */
	private static final int NODE_ICON_LINK_OFFSET = 10;

	
	/* ノードMap Canvas */
	private Canvas canvas;

	/* GC */
	private GC gc;

	// private Rectangle mapViewRectangle;
	private ScrolledComposite scrollComposite;

	private Point mapScrollCompositePoint;

	private int overviewPointX;

	private int overviewPointY;

	private int canvaAbsPointX;

	private int canvaAbsPointY;
	private int nodeMapViewWidth;
	private int nodeMapViewHeight;

	/* 概要スケール */
	private static final int OVERVIEW_POINT_SCALL = 20;

	/**
	 * ノードMap View描画クラスインスタンスを生成します。
	 * 
	 * @param canvas
	 *            Canvas
	 * @param gc
	 *            GC
	 */
	public NodeMapDrawViewDraw(ScrolledComposite scrollComposite, Canvas canvas,
			GC gc) {

		this.scrollComposite = scrollComposite;
		this.canvas = canvas;
		this.gc = gc;

	
		nodeMapViewWidth = CanvasViewConfigFileParse.getInstance().getNodeMapWidth();
		nodeMapViewHeight = CanvasViewConfigFileParse.getInstance().getNodeMapHeight();
		
		WHITE_COLOR = new Color(null, 255, 255, 255);
		BLACK_COLOR = new Color(null, 0, 0, 0);
		RED_COLOR = new Color(null, 255, 0, 0);
		TEST_COLOR = new Color(null, 127, 127, 127);
	}

	/**
	 * ノードLink及びノードを再描画します。
	 * 
	 * @param nodeMapNodeInfoList
	 *            ノードIcon情報リスト
	 * @param nodMapLinkInformationList
	 *            ノードリンク情報
	 */
	public void redraw(ArrayList nodeMapNodeInfoList,
			NodeMapLinkInformation nodMapLinkInformationList) {

		
		
		gc.fillRectangle(canvas.getClientArea());

		int height = canvas.getClientArea().height - 1;
		int width = canvas.getClientArea().width - 1;
		gc.setForeground(TEST_COLOR);
		gc.drawLine(0, 0, width, 0);
		gc.drawLine(0, 0, 0, height);
		gc.setForeground(WHITE_COLOR);
		gc.drawLine(width, 0, width, height);
		gc.drawLine(0, height, width, height);
		gc.setBackground(WHITE_COLOR);
		gc.setForeground(BLACK_COLOR);

		createOverviewPoint();
		setMapOverviewNode();

		/* ノード間Link描画 */
		drawNodeLink(nodeMapNodeInfoList, nodMapLinkInformationList);

		/* ノード描画 */
		drawNodeList(nodeMapNodeInfoList);

	}


	
	/**
	 * Map Overviewの描画位置をセットします。
	 * 
	 */
	protected void createOverviewPoint() {
		/* 全体CanvasにおけるViewの位置 */
		Point canvaPoint = canvas.getLocation();
		canvaAbsPointX = Math.abs(canvaPoint.x);
		canvaAbsPointY = Math.abs(canvaPoint.y);
		/* 表示しているMapビューサイズ */
		// mapViewRectangle = gc.getClipping();
		mapScrollCompositePoint = scrollComposite.getSize();
		overviewPointX = canvaAbsPointX;
		overviewPointY = canvaAbsPointY
				+ (mapScrollCompositePoint.y - (AbstractEditorNodeChart.OFFSET))
				- (nodeMapViewHeight/ OVERVIEW_POINT_SCALL);

	}

	/**
	 * Map Overviewを描画します。
	 * 
	 */
	protected void setMapOverviewNode() {

		gc.setForeground(BLACK_COLOR);
		/* Map Overview外枠 */
		gc.setLineStyle(SWT.LINE_DOT);
		gc.drawRectangle(overviewPointX, overviewPointY,
				nodeMapViewWidth / OVERVIEW_POINT_SCALL,
				nodeMapViewHeight / OVERVIEW_POINT_SCALL);
		/* Map viewの全体キャンバス上の位置 */
		gc.setLineWidth(2);
		gc.setLineStyle(SWT.LINE_SOLID);
		gc.drawRectangle(overviewPointX + canvaAbsPointX / OVERVIEW_POINT_SCALL,
				overviewPointY + canvaAbsPointY / OVERVIEW_POINT_SCALL,
				mapScrollCompositePoint.x / OVERVIEW_POINT_SCALL,
				mapScrollCompositePoint.y / OVERVIEW_POINT_SCALL);

		gc.setLineWidth(1);
	}

	/**
	 * Map OverviewにノードをDrawします。
	 * 
	 * @param nodex
	 *            ノードX座標
	 * @param nodey
	 *            ノードY座標
	 */
	protected void setMapOverviewNode(int nodex, int nodey) {

		gc.drawRectangle((overviewPointX + (nodex / OVERVIEW_POINT_SCALL)),
				(overviewPointY + (nodey / OVERVIEW_POINT_SCALL)), NODE_OVAL_VIEW_OFFSET, NODE_OVAL_VIEW_OFFSET);
	}


	/**
	 * ノードを描画します。
	 * 
	 * @param nodeMapNodeInfoList
	 *            ノードIcon情報リスト
	 */
	protected void drawNodeList(ArrayList nodeMapNodeInfoList) {
		setColor();

		for (int i = 0; i < nodeMapNodeInfoList.size(); i++) {
			/* ノードIcon imageを順次draw */
			NodeMapInfo nodeMapInfo = (NodeMapInfo) nodeMapNodeInfoList.get(i);
			int pointX = nodeMapInfo.getX();
			int pointY = nodeMapInfo.getY();
			gc.setForeground(BLACK_COLOR);
			
			if (!nodeMapInfo.isSelected()) {
				gc.drawImage(nodeMapInfo.getNodeIconImage(), pointX, pointY);

			} else {
				gc.drawImage(nodeMapInfo.getNodeIconImage(), pointX, pointY);
				gc.drawOval(pointX, pointY, nodeMapInfo.getWidth(), nodeMapInfo
						.getHeight());
			}
			setMapOverviewNode(pointX, pointY);
			/*
			 * ノード名,IPアドレスをIcon imageの下にセット
			 */
			gc.drawString(nodeMapInfo.getNodeInfo().getNodename(), pointX,
					pointY + NODE_NAME_Y_OFFSET);
			gc.drawString(nodeMapInfo.getNodeInfo().getIpaddress(), pointX,
					pointY + NODE_IPADDRESS_Y_OFFSET);

			/*
			 * アラーム情報セット
			 */
			NodeInformation nodeInfo = nodeMapInfo.getNodeInfo();

			if ((nodeInfo.getAlarmMessage() != null)
					&& !nodeInfo.getAlarmMessage().equals("")) {
				gc.setForeground(RED_COLOR);

				gc.drawString(nodeMapInfo.getNodeInfo().getAlarmDate() + " : "
						+ nodeMapInfo.getNodeInfo().getAlarmMessage(), pointX,
						pointY + 80);

				gc.drawLine(pointX, pointY, pointX + nodeMapInfo.getWidth(),
						pointY + nodeMapInfo.getHeight());
				gc.drawLine(pointX + nodeMapInfo.getWidth(), pointY, pointX,
						pointY + nodeMapInfo.getHeight());

				gc.setForeground(BLACK_COLOR);
			}
		}
	}

	/**
	 * ノード間Linkを描画します。
	 * 
	 * @param nodeMapNodeInfoList
	 *            ノードIcon情報リスト
	 * @param nodMapLinkInformationList
	 *            ノードリンク情報
	 */
	protected void drawNodeLink(ArrayList nodeMapNodeInfoList,
			NodeMapLinkInformation nodMapLinkInformationList) {
		if (nodMapLinkInformationList == null) {
			return;
		}

		ArrayList nodeLinkList0 = nodMapLinkInformationList.getNode0address();
		ArrayList nodeLinkList1 = nodMapLinkInformationList.getNode1address();

		/*
		 * ノードLink情報を順次抽出してノード間のLink描画
		 */
		for (int i = 0; i < nodeLinkList0.size(); i++) {
			String nodeX = (String) nodeLinkList0.get(i);
			String nodeY = (String) nodeLinkList1.get(i);
			for (int j = 0; j < nodeMapNodeInfoList.size(); j++) {
				NodeMapInfo nodeMapInfo = (NodeMapInfo) nodeMapNodeInfoList
						.get(j);
				NodeInformation nodeInfo = nodeMapInfo.getNodeInfo();
				if (nodeX.equals(nodeInfo.getIpaddress())) {
					for (int k = 0; k < nodeMapNodeInfoList.size(); k++) {
						NodeMapInfo nodeMapInfo2 = (NodeMapInfo) nodeMapNodeInfoList
								.get(k);
						NodeInformation nodeInfo2 = nodeMapInfo2.getNodeInfo();

						if (nodeY.equals(nodeInfo2.getIpaddress())) {
							int x0;
							int y0;
							int x1;
							int y1;

							x0 = (int) Float.parseFloat(nodeInfo.getNodeX())
									+ NODE_ICON_LINK_OFFSET;
							y0 = (int) Float.parseFloat(nodeInfo.getNodeY())
									+ NODE_ICON_LINK_OFFSET;
							x1 = (int) Float.parseFloat(nodeInfo2.getNodeX())
									+ NODE_ICON_LINK_OFFSET;
							y1 = (int) Float.parseFloat(nodeInfo2.getNodeY())
									+ NODE_ICON_LINK_OFFSET;
							gc.setForeground(BLACK_COLOR);
							gc.drawLine(x0, y0, x1, y1);
						}
					}
				}
			}
		}
	}

	/*
	 * Colorオブジェクトをセットします。
	 * 
	 */
	private void setColor() {
		/*
		 * Colorオブジェクトが破棄されていれば再セット
		 */
		if ((WHITE_COLOR == null) || WHITE_COLOR.isDisposed()) {
			WHITE_COLOR = new Color(null, 255, 255, 255);
		}

		if ((BLACK_COLOR == null) || BLACK_COLOR.isDisposed()) {
			BLACK_COLOR = new Color(null, 0, 0, 0);
		}

		if ((RED_COLOR == null) || RED_COLOR.isDisposed()) {
			RED_COLOR = new Color(null, 255, 0, 0);
		}

		if ((TEST_COLOR == null) || TEST_COLOR.isDisposed()) {
			TEST_COLOR = new Color(null, 127, 127, 127);
		}
	}

}
