using System.Collections.Generic;
using System.IO;

namespace Mafia2Tool.DataFormats.FrameResources
{
    /// <summary>
    /// contains: blendindex to joint index maps, bounding boxes...
    /// does NOT contain: joint names, joint transforms, joint hierachy...
    /// </summary>
    public class SkeletonBlendInfo : FrameResourceEntry
    {
        public class BlendDataToBoneIndexInfo
        {
            public int numBoneIndices;
            public int numBlendIndexRanges;

            public BlendDataToBoneIndexInfo(BinaryReader r)
            {
                Read(r);
            }

            public void Read(BinaryReader r)
            {
                numBoneIndices = r.ReadInt32();
                numBlendIndexRanges = r.ReadInt32();
            }
        }

        public class BlendDataToBoneIndexMap
        {
            public List<byte[]> BlendIndices;
            
            public byte[] BlendIndexRanges;

            public BlendDataToBoneIndexMap(BinaryReader r, BlendDataToBoneIndexInfo info)
            {
                Read(r, info);
            }

            public void Read(BinaryReader r, BlendDataToBoneIndexInfo info)
            {
                byte[] counts = r.ReadBytes(8);
                BlendIndices = new List<byte[]>();

                for (int i = 0; i < 8; i++)
                {
                    if (counts[i] != 0)
                    {
                        byte[] tmp = r.ReadBytes(counts[i]);
                        BlendIndices.Add(tmp);
                    }
                }

                // byte 0 = index to boneIndices list, byte 1 = max number of blend weights ???
                BlendIndexRanges = r.ReadBytes(info.numBlendIndexRanges * 2);
            }
        }

        public class BoundingBox
        {
            public TransformMatrix Transform; // world space = extract position matrix, extract rotation matrix, multiply -position * rotation
            public Bounds Bounds;
            public bool IsValid;

            public BoundingBox(BinaryReader r)
            {
                Read(r);
            }

            public void Read(BinaryReader r)
            {
                Transform = new TransformMatrix(r);
                this.Bounds = new Bounds(r);
                IsValid = r.ReadBoolean();
            }
        }

        BlendDataToBoneIndexInfo[] BlendDataToBoneIndexInfos;
        public Bounds Bounds;
        public BoundingBox[] BoundingBoxes;
        public BlendDataToBoneIndexMap[] BlendDataToBoneIndexMaps;

        public SkeletonBlendInfo(BinaryReader r, FrameResourceEntryList list)
            : base(list)
        {
            Read(r);
        }

        public void Read(BinaryReader r)
        {
            int numTransforms = r.ReadInt32();
            byte numblendDataToBoneIndexRefs = r.ReadByte();
            BlendDataToBoneIndexInfos = new BlendDataToBoneIndexInfo[numblendDataToBoneIndexRefs];
            for (int i = 0; i < numblendDataToBoneIndexRefs; i++)
            {
                BlendDataToBoneIndexInfos[i] = new BlendDataToBoneIndexInfo(r);
            }
            Bounds = new Bounds(r);
            BoundingBoxes = new BoundingBox[numTransforms];
            for (int i = 0; i < numTransforms; i++)
            {
                BoundingBoxes[i] = new BoundingBox(r);
            }

            BlendDataToBoneIndexMaps = new BlendDataToBoneIndexMap[numblendDataToBoneIndexRefs];
            for (int i = 0; i < numblendDataToBoneIndexRefs; i++)
            {
                BlendDataToBoneIndexMaps[i] = new BlendDataToBoneIndexMap(r, BlendDataToBoneIndexInfos[i]);
            }
        }

        public override string ToString()
        {
            return string.Format("SkeletonBlendInfo ({0})", Index);
        }    
    }
}
