using UnityEngine;
using System.Collections;

public class InverseKinematicsScript : MonoBehaviour 
{
	Vector3 target;
	Vector3 hinge_target;

	Transform upper;
	Transform hinge;
	Transform tail;

	public void SetTarget(Transform target)
	{
		this.target = target.position;
	}

	public void SetHingeTarget(Transform hinge)
	{
		this.hinge_target = hinge.position;
	}

	Transform SearchMoreChildTransform(Transform target)
	{
		int max = 0;
		int count = target.childCount;
		for (int i = 1; i < count; i++)
		{
			// 一番子供を持っているTransformを探してくる
			// 少なくともRigidbody用の奴は子供を持っていない
			if (target.GetChild(max).childCount < target.GetChild(i).childCount)
				max = i;
		}
		return target.GetChild(max);
	}

	void Start()
	{
		// 腕や足なので子供は一つのはずだろ！　JK！
		upper = SearchMoreChildTransform(transform);

		Debug.Log(upper.name);

		// 位置調整
		transform.position = upper.position;
		upper.localPosition = Vector3.zero;

		hinge = SearchMoreChildTransform(upper);
		tail = SearchMoreChildTransform(hinge);

		Debug.Log(hinge.name);
		Debug.Log(tail.name);
	}

	public void CalculateIK()
	{
		transform.LookAt(target, transform.position - hinge_target);

		// それぞれの長さを取得する
		var upper_length = Vector3.Distance(upper.position, hinge.position);
		var forearm_length = Vector3.Distance(hinge.position, tail.position);
		var arm_length = upper_length + forearm_length;

		var hypotenuse = upper_length;		// ???

		// ターゲットまでの距離を取る
		var target_distance = Vector3.Distance(upper.position, target);
		target_distance = Mathf.Min(target_distance, arm_length - 0.0001f);

		var adjacent = target_distance * (upper_length / arm_length);
		var ik_angle = Mathf.Acos(adjacent / hypotenuse) * Mathf.Rad2Deg;

		// 上腕（もも）の角度設定
		upper.LookAt(target, transform.root.up);
		var upper_angle = upper.localRotation.eulerAngles;
		upper_angle.x += ik_angle;
		upper.localRotation = Quaternion.Euler(upper_angle);	// 面倒くさい手順を踏んでセットする

		hinge.LookAt(target, transform.root.up);
	}
}
