package cc.stroketool;

import java.awt.Stroke;
import java.util.Vector;

import cc.movabletype.SeprateMovabletype;
import cc.stroke.ChineseCharacterTypeBolder;
import cc.movabletype.PlaneGeometry;

public class MkeSeparateMovableType_Bolder
{
	/** 物件活字加寬工具 */
	private final ChineseCharacterTypeBolder chineseCharacterTypeBolder;
	/** 合併、調整的精細度 */
	private final double precision;

	public MkeSeparateMovableType_Bolder(ChineseCharacterTypeBolder chineseCharacterTypeBolder,
			double precision)
	{
		this.chineseCharacterTypeBolder = chineseCharacterTypeBolder;
		this.precision = precision;
	}

	/**
	 * 計算物件活字粗細半徑
	 * 
	 * @param rectangularArea
	 *            物件活字
	 * @return 粗細半徑
	 */
	protected double computePieceRadius(PlaneGeometry rectangularArea)
	{
		ShapeInformation shapeInformation = new ShapeInformation(
				rectangularArea);
		return shapeInformation.getApproximativeRegion()
				/ shapeInformation.getApproximativeCircumference();
	}

	/**
	 * 計算物件活字粗細係數
	 * 
	 * @param rectangularArea
	 *            物件活字
	 * @return 粗細係數
	 */
	public double computeBoldCoefficient(PlaneGeometry rectangularArea)
	{
		return computePieceRadius(rectangularArea);
	}

	/**
	 * 利用二元搜尋法,找出符合粗細係數的物件活字筆劃加寬度
	 * 
	 * @param rectangularArea
	 *            物件活字
	 * @param originBoldCoefficient
	 *            粗細係數
	 * @return 筆劃加寬度
	 */
	protected PlaneGeometry 依寬度資訊產生外殼(PlaneGeometry 活字物件, MovableTypeWidthInfo 寬度資訊)
	{
		double 原來闊度系數 = 寬度資訊.取得活字粗細係數();
		MovableTypeWidthInfo 這馬闊度資訊 = 取得活字寬度資訊(活字物件);
		double 這馬闊度係數 = 這馬闊度資訊.取得活字粗細係數();
		// TODO 改成牛頓法可能比較好
		PlaneGeometry 新殼 = new PlaneGeometry();
		double miniWidth = 0.0, maxiWidth = 原來闊度系數 / 2.0;// TODO 奇怪參數
		while (miniWidth + getPrecision() < maxiWidth)
		{
			double middleWidth = 0.5 * (miniWidth + maxiWidth);
			新殼 = getBoldSurface(活字物件, middleWidth);

			double nowBoldCoefficient = computeBoldCoefficient(新殼);
			if (nowBoldCoefficient / 2.0 + 這馬闊度係數 < 原來闊度系數)
				miniWidth = middleWidth;
			else
				maxiWidth = middleWidth;
		}
		return 新殼;// getBoldSurface(活字物件, miniWidth);
	}

	/**
	 * 給定筆劃加寬度,取得物件活字外框
	 * 
	 * @param rectangularArea
	 *            物件活字
	 * @param strokeWidth
	 *            筆劃加寬度
	 * @return 物件活字外框
	 */
	protected PlaneGeometry getBoldSurface(PlaneGeometry rectangularArea, double strokeWidth)
	{
		if (strokeWidth < getPrecision())
			return new PlaneGeometry();
		Stroke stroke = chineseCharacterTypeBolder.getStroke(strokeWidth);
		return new PlaneGeometry(stroke.createStrokedShape(rectangularArea));
	}

	//
	// /**
	// * 固定粗細係數的情況下,縮小物件活字
	// * <p>
	// * 限制:<code>AffineTransform</code>二個縮放比例的絕對值必須小於等於1
	// *
	// * @param rectangularArea
	// * 物件活字
	// * @param affineTransform
	// * 粗細係數
	// */
	// void shrinkPieceByFixingStroke(SeprateMovabletype rectangularArea,
	// AffineTransform affineTransform)
	// {
	// // TODO
	// // MovableTypeWidthInfo 舊活字寬度資訊 = 取得活字寬度資訊(rectangularArea);
	// // // double originBoldCoefficient =
	// // // computeBoldCoefficient(rectangularArea);
	// // rectangularArea.縮放(affineTransform);
	// // 依寬度資訊調整活字(rectangularArea, 舊活字寬度資訊);
	// // // double strokeWidth = getStorkeWidthByCoefficient(rectangularArea,
	// // // originBoldCoefficient);
	// // // RectangularArea boldSurface = getBoldSurface(rectangularArea,
	// // // strokeWidth);
	// // // rectangularArea.add(boldSurface);
	// return;
	// }

	/**
	 * 取得活字物件的活字寬度資訊
	 * 
	 * @param 活字物件
	 *            欲取得資訊的活字物件
	 * @return MovableTypeWidthInfo
	 */
	MovableTypeWidthInfo 取得活字寬度資訊(PlaneGeometry 活字物件)
	{
		return new MovableTypeWidthInfo(computeBoldCoefficient(活字物件));
	}

	// /**
	// * 依照寬度資訊,來調整活字物件
	// *
	// * @param 活字物件
	// * 要被調整的活字物偉
	// * @param 寬度資訊
	// * 依據的寬度資訊
	// */
	// PlaneGeometry 依寬度資訊產生外殼(PlaneGeometry 活字物件, MovableTypeWidthInfo 寬度資訊)
	// {
	// // TODO
	// double strokeWidth = getStorkeWidthByCoefficient(活字物件, 寬度資訊.取得活字粗細係數());
	// PlaneGeometry boldSurface = getBoldSurface(活字物件, strokeWidth);
	// return boldSurface;
	// }

	/**
	 * 取得合併、調整的精細度
	 * 
	 * @return 合併、調整的精細度
	 */
	public double getPrecision()
	{
		return precision;
	}

	public void 加粗(SeprateMovabletype 活字)
	{
		Vector<PlaneGeometry> 原本字體 = 活字.提著原本字體();
		Vector<PlaneGeometry> 字 = 活字.提著字();
		if (原本字體.size() != 字.size())
		{
			System.err.println(原本字體.size());
			System.err.println(字.size());
			System.err.println("字佮原本字體數無仝!!");
			return;
		}
		Vector<PlaneGeometry> 字外殼 = new Vector<PlaneGeometry>();
		for (int i = 0; i < 原本字體.size(); ++i)
		{
			MovableTypeWidthInfo 寬度資訊 = 取得活字寬度資訊(原本字體.elementAt(i));
			字外殼.add(依寬度資訊產生外殼(字.elementAt(i), 寬度資訊));
		}
		活字.設字外殼(字外殼);
		return;
	}
}