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

[CustomEditor(typeof(T2SkinnedMeshMono))]
public class T2SkinnedMeshEditor : Editor
{
    public T2SkinnedMesh sMesh;

    public void LoadSkinnedMesh(string path)
    {
        IOUtils.readData = File.ReadAllBytes(path);
        IOUtils.readByteIndex = 0;

        sMesh.version = IOUtils.ReadInt32();
        sMesh.boundingBoxMin = IOUtils.ReadVector3();
        sMesh.boundingBoxMax = IOUtils.ReadVector3();
        sMesh.headTrackStartNode = IOUtils.ReadSByte();
        sMesh.headTrackEndNode = IOUtils.ReadSByte();
        sMesh.headTrackTrackFactor = IOUtils.ReadSByte();
        int nodeLength = IOUtils.ReadInt32();
        sMesh.nodes = new T2SkinnedMeshNode[nodeLength];
        for (int i = 0; i < nodeLength; i++)
        {
            sMesh.nodes[i] = new T2SkinnedMeshNode();
            T2SkinnedMeshNode node = sMesh.nodes[i];
            int childNodeLength = IOUtils.ReadInt32();
            node.childNodes = new short[childNodeLength];
            for (int j = 0; j < childNodeLength; j++)
            {
                node.childNodes[j] = IOUtils.ReadInt16();
            }
        }

        for (int i = 0; i < nodeLength; i++)
        {
            T2SkinnedMeshNode node = sMesh.nodes[i];
            node.boundingBoxMin = IOUtils.ReadVector3();
            node.boundingBoxMax = IOUtils.ReadVector3();
            node.impactType = IOUtils.ReadSByte();
            node.symbolFlags = IOUtils.ReadSByte();
            node.parentIndex = IOUtils.ReadSByte();
            node.damageScalar = IOUtils.ReadFloat();
            node.flags = IOUtils.ReadInt32();
        }

        sMesh.hotPointGroupCount = IOUtils.ReadInt32();
        int hotPointLength = IOUtils.ReadInt32();
        sMesh.hotPoints = new T2SkinnedMeshHotPoint[hotPointLength];
        for (int i = 0; i < hotPointLength; i++)
        {
            sMesh.hotPoints[i] = new T2SkinnedMeshHotPoint();
            T2SkinnedMeshHotPoint hotPoint = sMesh.hotPoints[i];
            hotPoint.origin = IOUtils.ReadVector3();
            hotPoint.flags = IOUtils.ReadInt32();
            hotPoint.boneID = IOUtils.ReadInt16();
            hotPoint.particleEffectID1 = IOUtils.ReadInt16();
            hotPoint.particleEffectID2 = IOUtils.ReadInt16();
        }

        sMesh.layers = IOUtils.ReadInt32();
        int surfaceLength = IOUtils.ReadInt32();
        sMesh.surfaces = new T2SkinnedMeshSurface[surfaceLength];
        for (int i = 0; i < surfaceLength; i++)
        {
            sMesh.surfaces[i] = new T2SkinnedMeshSurface();
            T2SkinnedMeshSurface surface = sMesh.surfaces[i];
            surface.materialFile = IOUtils.ReadString();
            List<Int16> triangleIndexes = new List<Int16>();
            while (true)
            {
                Int16 triIndex = IOUtils.ReadInt16();
                if (triIndex == -1)
                {
                    break;
                }
                triangleIndexes.Add(triIndex);
            }
            surface.triangleIndexes = triangleIndexes.ToArray();
        }

        int vertexLength = IOUtils.ReadInt32();
        sMesh.vertices = new T2SkinnedMeshVertex[vertexLength];
        for (int i = 0; i < vertexLength; i++)
        {
            sMesh.vertices[i] = new T2SkinnedMeshVertex();
            T2SkinnedMeshVertex vertex = sMesh.vertices[i];
            vertex.xyz = IOUtils.ReadVector3();
            vertex.uv = IOUtils.ReadVector2();
            vertex.normals = IOUtils.ReadVector3();
            vertex.nodeIndex = IOUtils.ReadInt16();
        }
    }

    public void SaveSkinnedMesh(string path)
    {
        IOUtils.writeData.Clear();

        IOUtils.WriteInt32(sMesh.version);
        IOUtils.WriteVector3(sMesh.boundingBoxMin);
        IOUtils.WriteVector3(sMesh.boundingBoxMax);
        IOUtils.WriteSByte(sMesh.headTrackStartNode);
        IOUtils.WriteSByte(sMesh.headTrackEndNode);
        IOUtils.WriteSByte(sMesh.headTrackTrackFactor);
        IOUtils.WriteInt32(sMesh.nodes.Length);
        for (int i = 0; i < sMesh.nodes.Length; i++)
        {
            T2SkinnedMeshNode node = sMesh.nodes[i];
            IOUtils.WriteInt32(node.childNodes.Length);
            for (int j = 0; j < node.childNodes.Length; j++)
            {
                IOUtils.WriteInt16(node.childNodes[j]);
            }
        }

        for (int i = 0; i < sMesh.nodes.Length; i++)
        {
            T2SkinnedMeshNode node = sMesh.nodes[i];
            IOUtils.WriteVector3(node.boundingBoxMin);
            IOUtils.WriteVector3(node.boundingBoxMax);
            IOUtils.WriteSByte(node.impactType);
            IOUtils.WriteSByte(node.symbolFlags);
            IOUtils.WriteSByte(node.parentIndex);
            IOUtils.WriteFloat(node.damageScalar);
            IOUtils.WriteInt32(node.flags);
        }

        IOUtils.WriteInt32(sMesh.hotPointGroupCount);
        IOUtils.WriteInt32(sMesh.hotPoints.Length);
        for (int i = 0; i < sMesh.hotPoints.Length; i++)
        {
            T2SkinnedMeshHotPoint hotPoint = sMesh.hotPoints[i];
            IOUtils.WriteVector3(hotPoint.origin);
            IOUtils.WriteInt32(hotPoint.flags);
            IOUtils.WriteInt16(hotPoint.boneID);
            IOUtils.WriteInt16(hotPoint.particleEffectID1);
            IOUtils.WriteInt16(hotPoint.particleEffectID2);
        }

        IOUtils.WriteInt32(sMesh.layers);
        IOUtils.WriteInt32(sMesh.surfaces.Length);
        for (int i = 0; i < sMesh.surfaces.Length; i++)
        {
            T2SkinnedMeshSurface surface = sMesh.surfaces[i];
            IOUtils.WriteString(surface.materialFile);
            for (int j = 0; j < surface.triangleIndexes.Length; j++)
            {
                IOUtils.WriteInt16(surface.triangleIndexes[j]);
            }
            IOUtils.WriteInt16(-1);
        }
        IOUtils.WriteInt32(sMesh.vertices.Length);
        for (int i = 0; i < sMesh.vertices.Length; i++)
        {
            T2SkinnedMeshVertex vertex = sMesh.vertices[i];
            IOUtils.WriteVector3(vertex.xyz);
            IOUtils.WriteVector2(vertex.uv);
            IOUtils.WriteVector3(vertex.normals);
            IOUtils.WriteInt16(vertex.nodeIndex);
        }

        File.WriteAllBytes(path, IOUtils.writeData.ToArray());
    }

    public override void OnInspectorGUI()
    {
        T2SkinnedMeshMono mb = target as T2SkinnedMeshMono;
        sMesh = mb.sMesh;

        GUILayout.BeginHorizontal();
        EditorGUIUtility.labelWidth = 80.0f;
        mb.loadPath = EditorGUILayout.TextField("Load Folder", mb.loadPath);
        EditorGUIUtility.labelWidth = 0.0f;
        if (GUILayout.Button("...", GUILayout.Width(32.0f)))
        {
            string path = EditorUtility.OpenFolderPanel("Load File Default Folder", mb.loadPath, "");
            if (!string.IsNullOrEmpty(path))
            {
                mb.loadPath = path;
            }
        }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        EditorGUIUtility.labelWidth = 80.0f;
        mb.savePath = EditorGUILayout.TextField("Save Folder", mb.savePath);
        EditorGUIUtility.labelWidth = 0.0f;
        if (GUILayout.Button("...", GUILayout.Width(32.0f)))
        {
            string path = EditorUtility.OpenFolderPanel("Save File Default Folder", mb.savePath, "");
            if (!string.IsNullOrEmpty(path))
            {
                mb.savePath = path;
            }
        }
        GUILayout.EndHorizontal();

        if (GUILayout.Button("Load File"))
        {
            string path = EditorUtility.OpenFilePanel("Open Skinnedmesh file", mb.loadPath, "skinnedmesh");
            if (!string.IsNullOrEmpty(path))
            {
                LoadSkinnedMesh(path);
            }
        }

        if (GUILayout.Button("Save File"))
        {
            string path = EditorUtility.SaveFilePanel("Save Skinnedmesh file", mb.savePath, "", "skinnedmesh");
            if (!string.IsNullOrEmpty(path))
            {
                SaveSkinnedMesh(path);
            }
        }

        base.OnInspectorGUI();

        EditorUtility.SetDirty(target);
    }
}
