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

public class ImportCM2 : MonoBehaviour
{
    public static byte[] m_aniTempFile = null;
    private static Dictionary<string, Material> m_dicCacheMaterial = new Dictionary<string, Material>();
    private static Dictionary<int, KeyValuePair<string, float>> m_hashPriorityMaterials;
    private static byte[] m_matTempFile;
    private static byte[] m_skinTempFile;

    private static string[] properties = new string[7]
    {
            "m_LocalRotation.x", "m_LocalRotation.y", "m_LocalRotation.z", "m_LocalRotation.w", "m_LocalPosition.x", "m_LocalPosition.y",
            "m_LocalPosition.z"
    };

    public static GameObject LoadSkinMesh_R(string filename, string[] filename2, string slotname, TBodySkin bodyskin, int layer)
    {
        try
        {
            using (AFileBase afileBase = GameUty.FileOpen(filename, null))
            {
                if (m_skinTempFile == null)
                    m_skinTempFile = new byte[Math.Max(500000, afileBase.GetSize())];
                else if (m_skinTempFile.Length < afileBase.GetSize())
                    m_skinTempFile = new byte[afileBase.GetSize()];
                afileBase.Read(ref m_skinTempFile, afileBase.GetSize());
            }
        }
        catch (Exception ex)
        {
            NDebug.Assert("ファイルが開けませんでした。" + filename + "\n" + ex.Message, false);
        }

        var r = new BinaryReader(new MemoryStream(m_skinTempFile), Encoding.UTF8);
        TBodySkin.OriVert oriVert = bodyskin.m_OriVert;
        var gameObject1 = Instantiate(Resources.Load("seed")) as GameObject;
        gameObject1.layer = layer;
        var gameObject2 = (GameObject) null;
        var hashtable = new Hashtable();
        string str1 = r.ReadString();
        if (str1 != "CM3D2_MESH")
            NDebug.Assert("LoadSkinMesh_R 例外 : ヘッダーファイルが不正です。" + str1, false);
        int num1 = r.ReadInt32();
        string str2 = r.ReadString();
        gameObject1.name = "_SM_" + str2;
        string str3 = r.ReadString();
        int num2 = r.ReadInt32();
        var gameObjectList = new List<GameObject>();
        for (int index = 0; index < num2; ++index)
        {
            var gameObject3 = Instantiate(Resources.Load("seed")) as GameObject;
            gameObject3.layer = layer;
            gameObject3.name = r.ReadString();
            gameObjectList.Add(gameObject3);
            if (gameObject3.name == str3)
                gameObject2 = gameObject3;
            hashtable[gameObject3.name] = gameObject3;
            if (r.ReadByte() != 0)
            {
                var gameObject4 = Instantiate(Resources.Load("seed")) as GameObject;
                gameObject4.name = gameObject3.name + "_SCL_";
                gameObject4.transform.parent = gameObject3.transform;
                hashtable[gameObject3.name + "&_SCL_"] = gameObject4;
            }
        }

        for (int index1 = 0; index1 < num2; ++index1)
        {
            int index2 = r.ReadInt32();
            gameObjectList[index1].transform.parent = index2 < 0 ? gameObject1.transform : gameObjectList[index2].transform;
        }

        for (int index = 0; index < num2; ++index)
        {
            Transform transform = gameObjectList[index].transform;
            float x1 = r.ReadSingle();
            float y1 = r.ReadSingle();
            float z1 = r.ReadSingle();
            transform.localPosition = new Vector3(x1, y1, z1);
            float x2 = r.ReadSingle();
            float y2 = r.ReadSingle();
            float z2 = r.ReadSingle();
            float w = r.ReadSingle();
            transform.localRotation = new Quaternion(x2, y2, z2, w);
            if (2001 <= num1 && r.ReadBoolean())
            {
                float x3 = r.ReadSingle();
                float y3 = r.ReadSingle();
                float z3 = r.ReadSingle();
                transform.localScale = new Vector3(x3, y3, z3);
            }
        }

        int length1 = r.ReadInt32();
        int length2 = r.ReadInt32();
        int length3 = r.ReadInt32();
        oriVert.VCount = length1;
        oriVert.nSubMeshCount = length2;
        gameObject2.AddComponent(typeof(SkinnedMeshRenderer));
        gameObject1.AddComponent(typeof(Animation));
        var component = gameObject2.GetComponent<Renderer>() as SkinnedMeshRenderer;
        component.updateWhenOffscreen = true;
        var transformArray = new Transform[length3];
        for (int index = 0; index < length3; ++index)
        {
            string str4 = r.ReadString();
            if (hashtable.ContainsKey(str4))
            {
                GameObject gameObject3 = !hashtable.ContainsKey(str4 + "&_SCL_")
                                                 ? (GameObject) hashtable[str4]
                                                 : (GameObject) hashtable[str4 + "&_SCL_"];
                transformArray[index] = gameObject3.transform;
            }
        }

        component.bones = transformArray;
        var mesh1 = new Mesh();
        component.sharedMesh = mesh1;
        Mesh mesh2 = mesh1;
        var matrix4x4Array = new Matrix4x4[length3];
        for (int index1 = 0; index1 < length3; ++index1)
        for (int index2 = 0; index2 < 16; ++index2)
            matrix4x4Array[index1][index2] = r.ReadSingle();
        mesh2.bindposes = matrix4x4Array;
        var vector3Array1 = new Vector3[length1];
        var vector3Array2 = new Vector3[length1];
        var vector2Array = new Vector2[length1];
        var boneWeightArray = new BoneWeight[length1];
        for (int index = 0; index < length1; ++index)
        {
            float new_x1 = r.ReadSingle();
            float new_y1 = r.ReadSingle();
            float new_z1 = r.ReadSingle();
            vector3Array1[index].Set(new_x1, new_y1, new_z1);
            float new_x2 = r.ReadSingle();
            float new_y2 = r.ReadSingle();
            float new_z2 = r.ReadSingle();
            vector3Array2[index].Set(new_x2, new_y2, new_z2);
            float newX = r.ReadSingle();
            float newY = r.ReadSingle();
            vector2Array[index].Set(newX, newY);
        }

        mesh2.vertices = vector3Array1;
        mesh2.normals = vector3Array2;
        mesh2.uv = vector2Array;
        oriVert.vOriVert = vector3Array1;
        oriVert.vOriNorm = vector3Array2;
        int length4 = r.ReadInt32();
        if (length4 > 0)
        {
            var vector4Array = new Vector4[length4];
            for (int index = 0; index < length4; ++index)
            {
                float x = r.ReadSingle();
                float y = r.ReadSingle();
                float z = r.ReadSingle();
                float w = r.ReadSingle();
                vector4Array[index] = new Vector4(x, y, z, w);
            }

            mesh2.tangents = vector4Array;
        }

        for (int index = 0; index < length1; ++index)
        {
            boneWeightArray[index].boneIndex0 = r.ReadUInt16();
            boneWeightArray[index].boneIndex1 = r.ReadUInt16();
            boneWeightArray[index].boneIndex2 = r.ReadUInt16();
            boneWeightArray[index].boneIndex3 = r.ReadUInt16();
            boneWeightArray[index].weight0 = r.ReadSingle();
            boneWeightArray[index].weight1 = r.ReadSingle();
            boneWeightArray[index].weight2 = r.ReadSingle();
            boneWeightArray[index].weight3 = r.ReadSingle();
        }

        mesh2.boneWeights = boneWeightArray;
        mesh2.subMeshCount = length2;
        oriVert.bwWeight = boneWeightArray;
        oriVert.nSubMeshCount = length2;
        oriVert.nSubMeshOriTri = new int[length2][];
        for (int submesh = 0; submesh < length2; ++submesh)
        {
            int length5 = r.ReadInt32();
            var triangles = new int[length5];
            for (int index = 0; index < length5; ++index)
                triangles[index] = r.ReadUInt16();
            oriVert.nSubMeshOriTri[submesh] = triangles;
            mesh2.SetTriangles(triangles, submesh);
        }

        int length6 = r.ReadInt32();
        var materialArray = new Material[length6];
        for (int index = 0; index < length6; ++index)
        {
            Material material = ReadMaterial(r, bodyskin, null, filename2[1 + index]);
            materialArray[index] = material;
        }

        component.materials = materialArray;
        r.Close();
        return gameObject1;
    }

    public static Material ReadMaterial(BinaryReader r, TBodySkin bodyskin, Material existmat, string filename)
    {
        bodyskin = null;
        existmat = null;
        if (m_hashPriorityMaterials == null)
        {
            m_hashPriorityMaterials = new Dictionary<int, KeyValuePair<string, float>>();
            var list = GameUty.FileSystem.GetList("prioritymaterial", AFileSystemBase.ListType.AllFile);
            if (list != null && 0 < list.Length)
                for (int index = 0; index < list.Length; ++index)
                    if (Path.GetExtension(list[index]) == ".pmat")
                    {
                        string fileName = list[index];
                        using (AFileBase afileBase = GameUty.FileOpen(fileName, null))
                        {
                            NDebug.Assert(afileBase.IsValid(), fileName + "を開けませんでした");
                            using (var binaryReader = new BinaryReader(new MemoryStream(afileBase.ReadAll()), Encoding.UTF8))
                            {
                                NDebug.Assert(binaryReader.ReadString() == "CM3D2_PMATERIAL", "ヘッダーエラー\n" + fileName);
                                binaryReader.ReadInt32();
                                int key1 = binaryReader.ReadInt32();
                                string key2 = binaryReader.ReadString();
                                float num = binaryReader.ReadSingle();
                                NDebug.Assert(!m_hashPriorityMaterials.ContainsKey(key1), "すでにハッシュが登録されています");
                                m_hashPriorityMaterials.Add(key1, new KeyValuePair<string, float>(key2, num));
                            }
                        }
                    }
        }

        string str1 = r.ReadString();
        string str2 = r.ReadString();
        string path1 = "DefMaterial/" + r.ReadString();
        Material material;
        if (existmat == null)
        {
            var original = Resources.Load(path1, typeof(Material)) as Material;
            if (original == null)
                return original;
            material = Instantiate(original);
        }
        else
        {
            material = existmat;
            NDebug.Assert(material.shader.name == str2, "マテリアル入れ替えエラー。違うシェーダーに入れようとしました。 " + str2 + " -> " + material.shader.name);
        }

        material.name = str1;
        int hashCode1 = material.name.GetHashCode();
        if (m_hashPriorityMaterials != null && m_hashPriorityMaterials.ContainsKey(hashCode1))
        {
            var priorityMaterial = m_hashPriorityMaterials[hashCode1];
            if (priorityMaterial.Key == material.name)
            {
                material.SetFloat("_SetManualRenderQueue", priorityMaterial.Value);
                material.renderQueue = (int) priorityMaterial.Value;
            }
        }

        string str3;
        Vector2 vector2_1;
        Vector2 vector2_2;
        string str4;
        string str5;
        Color color;
        Vector4 vector4;
        while (true)
        {
            string str6 = r.ReadString();
            if (!(str6 == "end"))
            {
                string name = r.ReadString();
                if (str6 == "tex")
                {
                    string str7 = r.ReadString();
                    if (str7 == "null")
                    {
                        material.SetTexture(name, null);
                    }
                    else if (str7 == "tex2d")
                    {
                        try
                        {
                            string str8 = r.ReadString();
                            str3 = r.ReadString();
                            var data = ImportCM.LoadTexture(GameUty.FileSystem, str8 + ".tex", false).data;
                            vector2_1.x = r.ReadSingle();
                            vector2_1.y = r.ReadSingle();
                            vector2_2.x = r.ReadSingle();
                            vector2_2.y = r.ReadSingle();
                            if (filename == null || !filename.Contains(".mate"))
                            {
                                var texture2D = new Texture2D(1, 1, TextureFormat.RGBA32, false);
                                texture2D.LoadImage(data);
                                texture2D.name = str8;
                                texture2D.wrapMode = TextureWrapMode.Clamp;
                                material.SetTexture(name, texture2D);
                                material.SetTextureOffset(name, vector2_1);
                                material.SetTextureScale(name, vector2_2);
                            }
                        }
                        catch
                        {
                            break;
                        }
                    }
                    else if (str7 == "texRT")
                    {
                        str4 = r.ReadString();
                        str5 = r.ReadString();
                    }
                }
                else if (str6 == "col")
                {
                    color.r = r.ReadSingle();
                    color.g = r.ReadSingle();
                    color.b = r.ReadSingle();
                    color.a = r.ReadSingle();
                    material.SetColor(name, color);
                }
                else if (str6 == "vec")
                {
                    vector4.x = r.ReadSingle();
                    vector4.y = r.ReadSingle();
                    vector4.z = r.ReadSingle();
                    vector4.w = r.ReadSingle();
                    material.SetVector(name, vector4);
                }
                else if (str6 == "f")
                {
                    float num = r.ReadSingle();
                    material.SetFloat(name, num);
                }
            }
            else
            {
                break;
            }
        }

        if (filename != null && filename.Contains(".mate"))
        {
            try
            {
                using (AFileBase afileBase = GameUty.FileOpen(filename, null))
                {
                    if (m_matTempFile == null)
                        m_matTempFile = new byte[Math.Max(10000, afileBase.GetSize())];
                    else if (m_matTempFile.Length < afileBase.GetSize())
                        m_matTempFile = new byte[afileBase.GetSize()];
                    afileBase.Read(ref m_matTempFile, afileBase.GetSize());
                }
            }
            catch { }

            var binaryReader = new BinaryReader(new MemoryStream(m_matTempFile), Encoding.UTF8);
            string str6 = binaryReader.ReadString();
            NDebug.Assert(str6 == "CM3D2_MATERIAL", "ProcScriptBin 例外 : ヘッダーファイルが不正です。" + str6);
            binaryReader.ReadInt32();
            binaryReader.ReadString();
            r = binaryReader;
            string str7 = r.ReadString();
            string str8 = r.ReadString();
            string path2 = "DefMaterial/" + r.ReadString();
            if (existmat == null)
            {
                var original = Resources.Load(path2, typeof(Material)) as Material;
                if (original == null)
                    return original;
                material = Instantiate(original);
            }
            else
            {
                material = existmat;
                NDebug.Assert(material.shader.name == str8, "マテリアル入れ替えエラー。違うシェーダーに入れようとしました。 " + str8 + " -> " + material.shader.name);
            }

            material.name = str7;
            int hashCode2 = material.name.GetHashCode();
            if (m_hashPriorityMaterials != null && m_hashPriorityMaterials.ContainsKey(hashCode2))
            {
                var priorityMaterial = m_hashPriorityMaterials[hashCode2];
                if (priorityMaterial.Key == material.name)
                {
                    material.SetFloat("_SetManualRenderQueue", priorityMaterial.Value);
                    material.renderQueue = (int) priorityMaterial.Value;
                }
            }

            while (true)
            {
                string str9 = r.ReadString();
                if (!(str9 == "end"))
                {
                    string name = r.ReadString();
                    if (str9 == "tex")
                    {
                        string str10 = r.ReadString();
                        if (str10 == "null")
                        {
                            material.SetTexture(name, null);
                        }
                        else if (str10 == "tex2d")
                        {
                            try
                            {
                                string str11 = r.ReadString();
                                str3 = r.ReadString();
                                var data = ImportCM.LoadTexture(GameUty.FileSystem, str11 + ".tex", false).data;
                                var texture2D = new Texture2D(1, 1, TextureFormat.RGBA32, false);
                                texture2D.LoadImage(data);
                                texture2D.name = str11;
                                texture2D.wrapMode = TextureWrapMode.Clamp;
                                material.SetTexture(name, texture2D);
                                vector2_1.x = r.ReadSingle();
                                vector2_1.y = r.ReadSingle();
                                material.SetTextureOffset(name, vector2_1);
                                vector2_2.x = r.ReadSingle();
                                vector2_2.y = r.ReadSingle();
                                material.SetTextureScale(name, vector2_2);
                            }
                            catch
                            {
                                break;
                            }
                        }
                        else if (str10 == "texRT")
                        {
                            str4 = r.ReadString();
                            str5 = r.ReadString();
                        }
                    }
                    else if (str9 == "col")
                    {
                        color.r = r.ReadSingle();
                        color.g = r.ReadSingle();
                        color.b = r.ReadSingle();
                        color.a = r.ReadSingle();
                        material.SetColor(name, color);
                    }
                    else if (str9 == "vec")
                    {
                        vector4.x = r.ReadSingle();
                        vector4.y = r.ReadSingle();
                        vector4.z = r.ReadSingle();
                        vector4.w = r.ReadSingle();
                        material.SetVector(name, vector4);
                    }
                    else if (str9 == "f")
                    {
                        float num = r.ReadSingle();
                        material.SetFloat(name, num);
                    }
                }
                else
                {
                    break;
                }
            }
        }

        return material;
    }
}