﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

namespace HALBY.Utility
{
}

public class CopyDynamicBones : EditorWindow
{
    private GameObject _referenceObject;
    private GameObject _targetObject;

    [MenuItem("HALBY/Copy Dynamic Bones")]
    private static void Create()
    {
        GetWindow<CopyDynamicBones>("Copy Dynamic Bones");
    }

    private void OnGUI()
    {
        _referenceObject =
            EditorGUILayout.ObjectField("Reference Avatar Object", _referenceObject, typeof(GameObject), true) as
                GameObject;
        _targetObject =
            EditorGUILayout.ObjectField("Target Avatar Object", _targetObject, typeof(GameObject), true) as GameObject;
        if (_referenceObject != null && _targetObject != null && GUILayout.Button("Copy!"))
        {
            Undo.RecordObject(_targetObject, "Copy Dynamic Bones");

            // 重そうなので最初にループ
            var targetTransforms = _targetObject.transform.GetComponentsInChildren<Transform>();

            // 先にコライダー
            var colliders = _referenceObject.GetComponentsInChildren<DynamicBoneCollider>();
            foreach (var collider in colliders)
            {
                ComponentUtility.CopyComponent(collider);
                var target = targetTransforms.FirstOrDefault(t => collider.transform.name == t.name);
                if (target) ComponentUtility.PasteComponentAsNew(target.gameObject);
            }

            var targetColliders = _targetObject.GetComponentsInChildren<DynamicBoneCollider>();

            var dbInfos = _referenceObject.GetComponentsInChildren<DynamicBone>()
                .Select(db => new KeyValuePair<string, DynamicBone>(db.name, db));

            foreach (var dbInfo in dbInfos)
            {
                // クリップボードにコピーしておく
                ComponentUtility.CopyComponent(dbInfo.Value);

                var targetObj = targetTransforms.FirstOrDefault(t => t.name == dbInfo.Key);

                if (targetObj != null)
                {
                    // DB重複回避
                    var duplicateDb = targetObj.GetComponents<DynamicBone>()
                        .FirstOrDefault(db => db.m_Root == dbInfo.Value.transform);
                    if (duplicateDb) Destroy(duplicateDb);

                    var newDb = targetObj.gameObject.AddComponent<DynamicBone>();
                    ComponentUtility.PasteComponentValues(newDb);
                    FixBoneTarget(newDb, targetTransforms, targetColliders);
                }
                else
                {
                    // ルート直下にDynamic Bonesというオブジェクトを生成しそこに全部張り付ける
                    var dbObj = _targetObject.transform.Find("Dynamic Bones");
                    if (!dbObj)
                    {
                        dbObj = new GameObject().transform;
                        dbObj.parent = _targetObject.transform;
                        dbObj.name = "Dynamic Bone";
                    }

                    // DB重複回避
                    var duplicateDb = dbObj.GetComponents<DynamicBone>()
                        .FirstOrDefault(db => db.m_Root == dbInfo.Value.transform);
                    if (duplicateDb) Destroy(duplicateDb);

                    var newDb = dbObj.gameObject.AddComponent<DynamicBone>();
                    ComponentUtility.PasteComponentValues(newDb);
                    FixBoneTarget(newDb, targetTransforms, targetColliders);
                }
            }
        }
    }

    private void FixBoneTarget(DynamicBone db, Transform[] transforms, DynamicBoneCollider[] colliders)
    {
        var target = transforms.FirstOrDefault(t => db.m_Root.name == t.name);
        Debug.Log(target, target);
        if (!target) return;
        db.m_Root = target;
        db.m_Colliders = db.m_Colliders.Select(dbc => colliders.FirstOrDefault(c => dbc && c.name == dbc.name) as DynamicBoneColliderBase)
            .ToList();
    }
}