using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

/// <summary>
/// 表情の管理クラス
/// </summary>
public class ExpressionManagerScript : MonoBehaviour
{
	// モーフもされていない生成されたばかりの頂点の元の位置
	public Dictionary<int, Vector3> source_position = new Dictionary<int, Vector3>();

	// 元頂点に対して合成したいベクトル
	// source + composite -> Meshの頂点
	public Dictionary<int, Vector3> composite_vector = new Dictionary<int, Vector3>();

	MMDSkinsScript[] skin_script;	// 子供の表情のスクリプト配列

	Mesh mesh;	// メッシュ

	void Start()
	{
		skin_script = GetSkinScripts();

		// メッシュを取得
		mesh = transform.parent.gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh;

		// モーフされてない頂点を辞書配列に格納する
		foreach (var script in skin_script)
		{
			foreach (var index in script.targetIndices)
			{
				// キーを持っていなかったら頂点を追加する
				if (!source_position.ContainsKey(index))
				{
					source_position.Add(index, mesh.vertices[index]);
					composite_vector.Add(index, Vector3.zero);
				}
			}
		}
	}

	// SkinScriptの配列を子供の表情から探して拾ってくる
	MMDSkinsScript[] GetSkinScripts()
	{
		// Expressionを探して拾う
		int count = transform.GetChildCount();
		Transform t = transform;
		for (int i = 0; i < count; i++)
		{
			t = transform.GetChild(i);
			if (t.gameObject.name == "Expression") break;
		}

		// 表情のスクリプトを拾ってくる
		count = t.GetChildCount();
		var scripts = new MMDSkinsScript[count];
		for (int i = 0; i < count; i++)
			scripts[i] = t.GetChild(i).GetComponent<MMDSkinsScript>();

		return scripts;
	}

	void Update()
	{
		int animated_skin_count = 0;
		for (int i = 0; i < skin_script.Length; i++)
		{
			// 表情のウェイト値が更新されていたら計算を行う
			if (skin_script[i].IsAnimate)
			{
				animated_skin_count++;

				skin_script[i].Compute();	// モーフの計算を行う

				for (int j = 0; j < skin_script[i].resultMorph.Length; j++)
					composite_vector[skin_script[i].targetIndices[j]] += skin_script[i].resultMorph[j];
			}
		}

		// 動作したアニメーションの数で割る
		// float division_count = 1f / animated_skin_count;
		foreach (var i in composite_vector.Keys)
		{
			//composite_vector[i] *= division_count;	// 平均取る意味がないのと、失敗する可能性がある
			mesh.vertices[i] = composite_vector[i] + source_position[i];	// 頂点座標 = 合成 + 元頂点
			composite_vector[i] = Vector3.zero;		// 次のフレームに備えて初期化する
		}

	}
}
