// Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,
// for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.
// EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileLoader
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

public class ProfileLoader
{
    private ProfileData loadedProfileData;

    private const int HEX32_W = 8;

    public List<string> GetProfileList()
    {
        ProfileUtils profileUtils = new ProfileUtils();
        string text = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
        List<string> list = new List<string>();
        if (!Directory.Exists(text))
        {
            Debug.LogWarning("[ProfileUtils] Profile base path does not exist: " + text);
            return list;
        }
        string[] directories = Directory.GetDirectories(text);
        foreach (string text2 in directories)
        {
            string fileName = Path.GetFileName(text2);
            if (!string.IsNullOrEmpty(fileName))
            {
                string path = Path.Combine(text2, fileName + ".json");
                string path2 = Path.Combine(text2, fileName + ".eb");
                if (File.Exists(path) && File.Exists(path2))
                {
                    list.Add(fileName);
                }
            }
        }
        return list;
    }

    public ProfileData LoadProfileData(string profileName)
    {
        ProfileUtils profileUtils = new ProfileUtils();
        string path = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
        path = Path.Combine(path, profileName);
        path = Path.Combine(path, profileName + ".json");
        if (string.IsNullOrWhiteSpace(path))
        {
            throw new AutoMorpherException("Profile File Path is Invalid", "[ProfileLoader] LoadProfileData\n - Profile Path is null, empty, or whitespace");
        }
        if (!File.Exists(path))
        {
            throw new AutoMorpherException("Profile File Does Not Exist", "[ProfileLoader] LoadProfileData\n - profile file does not exist\n - path : " + path);
        }
        string json = File.ReadAllText(path);
        this.loadedProfileData = JsonUtility.FromJson<ProfileData>(json);
        if (this.loadedProfileData == null)
        {
            throw new AutoMorpherException("Failed to Load Profile Data", "[ProfileLoader] LoadProfileData\n - Can't Load Profile Data\n - Please place a valid profile data file at " + path);
        }
        return this.loadedProfileData;
    }

    public BvhTriangleMesh LoadBvhWithRootTransform(Transform rootTransform, string profileName)
    {
        ProfileUtils profileUtils = new ProfileUtils();
        string path = Path.Combine(Application.dataPath, profileUtils.GetProfileBasePath());
        path = Path.Combine(path, profileName);
        path = Path.Combine(path, profileName + ".eb");
        if (rootTransform == null)
        {
            throw new AutoMorpherException("Root Transform is Null", "[ProfileLoader] LoadBvhWithRootTransform\n - rootTransform is null");
        }
        if (string.IsNullOrEmpty(path))
        {
            throw new AutoMorpherException("Profile BVH Path is Invalid", "[ProfileLoader] LoadBvhWithRootTransform\n - profileBvhPath is null or empty");
        }
        int version;
        ProfileBVH profileBVH = this.LoadProfileBVHData(path, out version);
        if (profileBVH == null || profileBVH.vertices == null || profileBVH.datas == null || profileBVH.nodes == null || profileBVH.dataIndices == null)
        {
            throw new AutoMorpherException("Profile BVH Data is Invalid", "[ProfileLoader] LoadBvhWithRootTransform\n - profile or one of its internal data fields is null");
        }
        Matrix4x4 localToWorldMatrix = rootTransform.localToWorldMatrix;
        int num = profileBVH.datas.Length;
        BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh
        {
            triangles = new BvhTriangle[num],
            triIndices = new int[profileBVH.dataIndices.Length],
            nodes = new BvhNode[profileBVH.nodes.Length]
        };
        for (int i = 0; i < num; i++)
        {
            profileBVHData profileBVHData2 = profileBVH.datas[i];
            Vector3 point = profileBVH.vertices[profileBVHData2.verA];
            Vector3 point2 = profileBVH.vertices[profileBVHData2.verB];
            Vector3 point3 = profileBVH.vertices[profileBVHData2.verC];
            Vector3 a = localToWorldMatrix.MultiplyPoint3x4(point);
            Vector3 b = localToWorldMatrix.MultiplyPoint3x4(point2);
            Vector3 c = localToWorldMatrix.MultiplyPoint3x4(point3);
            Vector3 normal = this.ComputeTriangleNormal(a, b, c);
            bvhTriangleMesh.triangles[i] = new BvhTriangle
            {
                a = a,
                b = b,
                c = c,
                normal = normal,
                mainHumanBone = HumanBodyBones.LastBone
            };
        }
        Array.Copy(profileBVH.dataIndices, bvhTriangleMesh.triIndices, profileBVH.dataIndices.Length);
        for (int j = 0; j < profileBVH.nodes.Length; j++)
        {
            profileBVHNode profileBVHNode2 = profileBVH.nodes[j];
            bvhTriangleMesh.nodes[j] = new BvhNode
            {
                isLeaf = profileBVHNode2.isLeaf,
                leftChild = profileBVHNode2.leftChild,
                rightChild = profileBVHNode2.rightChild,
                start = profileBVHNode2.start,
                count = profileBVHNode2.count,
                bounds = this.TransformBoundsToWorldAABB(localToWorldMatrix, profileBVHNode2.bounds)
            };
        }
        return bvhTriangleMesh;
    }

    private ProfileBVH LoadProfileBVHData(string path, out int version)
    {
        version = 0;
        int num = 0;
        if (!File.Exists(path))
        {
            throw new AutoMorpherException("Profile BVH File Not Found", "[ProfileLoader] LoadProfileBVHData\n - file not found\n - path : " + path);
        }
        string text = File.ReadAllText(path, Encoding.UTF8);
        int num2 = 0;
        ProfileUtils profileUtils = new ProfileUtils();
        string profileMagic = profileUtils.GetProfileMagic();
        if (text.Length < profileMagic.Length || text.Substring(0, profileMagic.Length) != profileMagic)
        {
            throw new AutoMorpherException("Profile BVH Magic Mismatch", "[ProfileLoader] LoadProfileBVHData\n - magic string mismatch\n - invalid or corrupted BVH file");
        }
        num2 += profileMagic.Length;
        version = this.ReadHexIntSafe(text, ref num2);
        num = this.ReadHexIntSafe(text, ref num2);
        int num3 = this.ReadHexIntSafe(text, ref num2);
        int num4 = this.ReadHexIntSafe(text, ref num2);
        int num5 = this.ReadHexIntSafe(text, ref num2);
        int num6 = this.ReadHexIntSafe(text, ref num2);
        if (num3 < 0 || num4 < 0 || num5 < 0 || num6 < 0)
        {
            throw new AutoMorpherException("Profile BVH Count Data is Invalid", "[ProfileLoader] LoadProfileBVHData\n - one or more count values are negative");
        }
        Vector3[] array = new Vector3[num3];
        for (int i = 0; i < num3; i++)
        {
            array[i] = this.ReadHexVec3Safe(text, ref num2);
        }
        int version2;
        int countInFile;
        BaseKey3[] array2 = new ProfileUtils_VertexUtil().LoadTable(profileUtils.GetBaseDataPath(), out version2, out countInFile);
        if (array2 == null || array2.Length == 0)
        {
            throw new AutoMorpherException("Profile BVH Base Vertex Table is Invalid", "[ProfileLoader] LoadProfileBVHData\n - base vertex table is null or empty");
        }
        ProfileUtil_IndexUtil profileUtil_IndexUtil = new ProfileUtil_IndexUtil();
        profileUtil_IndexUtil.Build(num);
        Vector3[] array3 = new Vector3[num3];
        profileUtil_IndexUtil.DecodeInto(array, array3);
        Vector3[] array4 = new Vector3[num3];
        for (int j = 0; j < num3; j++)
        {
            array4[j] = this.TransformVec3(array3[j], array2[j % array2.Length]);
        }
        ProfileBVH profileBVH = new ProfileBVH
        {
            vertices = new List<Vector3>(num3),
            datas = new profileBVHData[num4],
            nodes = new profileBVHNode[num5],
            dataIndices = new int[num6]
        };
        profileBVH.vertices.AddRange(array4);
        for (int k = 0; k < num4; k++)
        {
            profileBVH.datas[k] = new profileBVHData
            {
                verA = this.ReadHexIntSafe(text, ref num2),
                verB = this.ReadHexIntSafe(text, ref num2),
                verC = this.ReadHexIntSafe(text, ref num2)
            };
        }
        for (int l = 0; l < num5; l++)
        {
            Vector3 center = this.ReadHexVec3Safe(text, ref num2);
            Vector3 vector = this.ReadHexVec3Safe(text, ref num2);
            profileBVH.nodes[l] = new profileBVHNode
            {
                bounds = new Bounds(center, vector * 2f),
                leftChild = this.ReadHexIntSafe(text, ref num2),
                rightChild = this.ReadHexIntSafe(text, ref num2),
                start = this.ReadHexIntSafe(text, ref num2),
                count = this.ReadHexIntSafe(text, ref num2),
                isLeaf = (num2 < text.Length && text[num2++] == '1')
            };
        }
        for (int m = 0; m < num6; m++)
        {
            profileBVH.dataIndices[m] = this.ReadHexIntSafe(text, ref num2);
        }
        return profileBVH;
    }

    private int ReadHexIntSafe(string s, ref int p)
    {
        if (p + 8 > s.Length)
        {
            p = s.Length;
            throw new AutoMorpherException("Profile BVH ReadHexInt Out of Range", "[ProfileBVH] ReadHexIntSafe\n - read position exceeds string length");
        }
        uint result = Convert.ToUInt32(s.Substring(p, 8), 16);
        p += 8;
        return (int)result;
    }

    private Vector3 ReadHexVec3Safe(string s, ref int p)
    {
        return new Vector3(this.ReadHexFloatSafe(s, ref p), this.ReadHexFloatSafe(s, ref p), this.ReadHexFloatSafe(s, ref p));
    }

    private float ReadHexFloatSafe(string s, ref int p)
    {
        if (p + 8 > s.Length)
        {
            p = s.Length;
            throw new AutoMorpherException("Profile BVH ReadHexFloat Out of Range", "[ProfileBVH] ReadHexFloat\n - read position exceeds string length");
        }
        uint value = Convert.ToUInt32(s.Substring(p, 8), 16);
        p += 8;
        return BitConverter.Int32BitsToSingle((int)value);
    }

    private Vector3 TransformVec3(Vector3 v, BaseKey3 k)
    {
        return new Vector3(this.TransformFloatBits(v.x, k.x), this.TransformFloatBits(v.y, k.y), this.TransformFloatBits(v.z, k.z));
    }

    private float TransformFloatBits(float a, uint keyBits)
    {
        return BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(a) ^ (int)keyBits);
    }

    private Vector3 ComputeTriangleNormal(Vector3 a, Vector3 b, Vector3 c)
    {
        Vector3 vector = Vector3.Cross(b - a, c - a);
        float magnitude = vector.magnitude;
        if (magnitude > 1E-08f)
        {
            return vector / magnitude;
        }
        return Vector3.up;
    }

    private Bounds TransformBoundsToWorldAABB(Matrix4x4 l2w, Bounds localBounds)
    {
        Vector3 center = localBounds.center;
        Vector3 extents = localBounds.extents;
        Vector3 vector = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z));
        Vector3 p = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, 0f - extents.y, extents.z));
        Vector3 p2 = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, extents.y, 0f - extents.z));
        Vector3 p3 = l2w.MultiplyPoint3x4(center + new Vector3(0f - extents.x, extents.y, extents.z));
        Vector3 p4 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z));
        Vector3 p5 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, 0f - extents.y, extents.z));
        Vector3 p6 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, extents.y, 0f - extents.z));
        Vector3 p7 = l2w.MultiplyPoint3x4(center + new Vector3(extents.x, extents.y, extents.z));
        Vector3 min = vector;
        Vector3 max = vector;
        this.Encapsulate(ref min, ref max, p);
        this.Encapsulate(ref min, ref max, p2);
        this.Encapsulate(ref min, ref max, p3);
        this.Encapsulate(ref min, ref max, p4);
        this.Encapsulate(ref min, ref max, p5);
        this.Encapsulate(ref min, ref max, p6);
        this.Encapsulate(ref min, ref max, p7);
        return new Bounds((min + max) * 0.5f, max - min);
    }

    private void Encapsulate(ref Vector3 min, ref Vector3 max, Vector3 p)
    {
        min = Vector3.Min(min, p);
        max = Vector3.Max(max, p);
    }
}
