/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: DefaultTopologyDrawer.java,v 1.7 2005/08/18 00:02:44 rampil Exp $
 */
package org.logical_paradox.gdrn.shell.command.topo;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import org.logical_paradox.rss.dsr.routing.Node;

/**
 * デフォルトのトポロジー描画ロジック
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.7 $
 */
public class DefaultTopologyDrawer implements TopologyDrawer {
	/** sinテーブル */
	private static double[] tblSin;
	/** cosテーブル */
	private static double[] tblCos;

	/*
	 * sin,cosテーブルを事前に作成しておく
	 */
	static {
		// sin,cosテーブルの初期化
		tblSin = new double[360];
		tblCos = new double[360];
		for(int i = 0; i < 360; i++) {
			tblSin[i] = Math.sin(Math.toRadians(i));
			tblCos[i] = Math.cos(Math.toRadians(i));
		}
	}
	/**
	 * ノードを描画する
	 * @param g 描画対象リージョン
	 * @param node ノード
	 * @param x X座標
	 * @param y Y座標
	 */
	protected void drawNode(Graphics g, Node node, int x, int y) {
		Rectangle rect = new Rectangle(x, y, TopologyConstant.NODE_DRAW_WIDTH, TopologyConstant.NODE_DRAW_HEIGHT);

		g.setColor(TopologyConstant.DEFAULT_FORE_COLOR);
		g.drawRect((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), (int)rect.getHeight());
	}
	/**
	 * トポロジーを描画する
	 * @param g 描画対象リージョン
	 * @param topo 描画するトポロジー
	 */
	public void paint(Graphics g, Topology topo) {
		// ブラシの設定
		Color prevColor = g.getColor();

		// 今注目しているノードの座標を求める
		int x = (g.getClipBounds().width - TopologyConstant.NODE_DRAW_WIDTH) /2;
		int y = (g.getClipBounds().height - TopologyConstant.NODE_DRAW_HEIGHT) /2;

		Node begin = topo.getNode(0);
		if(begin == null) {
			return;
		}
		drawNode(g, begin, x, y);

		// 全ノードを配置する
		int nodes = topo.getNodeListSize();
		int degree = 0;
		for(int i = 1; i < nodes; i++) {
			Node node = topo.getNode(i);
			// 起点との距離を計測する
			// 計測結果はキャッシュされる
			double distance = node.distanceFrom(begin);
			int xx = x + (int)(distance / 10 * tblCos[degree]);
			int yy = y + (int)(distance / 10 * tblSin[degree]);
			drawNode(g, node, xx, yy);

			g.setColor(Color.CYAN);
			g.drawLine(x + TopologyConstant.NODE_DRAW_WIDTH / 2, y + TopologyConstant.NODE_DRAW_HEIGHT / 2,
						 xx + TopologyConstant.NODE_DRAW_WIDTH / 2, yy + TopologyConstant.NODE_DRAW_HEIGHT / 2
			);

			degree += 360 / TopologyConstant.NODES_PER_ROUND;
			degree %= 260;
		}

		// ブラシを元に戻す
		g.setColor(prevColor);
	}
}
