using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mafia2Tool.Parsed
{
    public class SkeletonJoint
    {
        private Skeleton _col;

        public int Index { get; private set; }
        public int ParentIndex { get; private set; }
        public Hash Name { get; private set; }
        public int LodFlag { get; private set; }

        private int _lodIndex;
        public bool HasBounds
        { 
            get 
            {
                int flag = (1 << _lodIndex);
                return (LodFlag & flag) == flag;
            }
        }
        
        public Bounds Bounds { get; private set; }

        private TransformMatrix _boundsTransform;
        public Matrix44 BoundsTransformWorld
        {
            get
            {
                Matrix44 position = new Matrix44(_boundsTransform.Translation);
                Matrix44 rotation = new Matrix44(_boundsTransform.Rotation);
                return position * rotation;
            }
        }

        private TransformMatrix _jointTransform;
        
        #region computed from _jointTransform... 
        public Matrix33 TransformLocalRotation
        {
            get { return _jointTransform.Rotation; }
        }

        protected Matrix33 TransformLocalRotationTransposed
        {
            get
            {
                Matrix33 mat = TransformLocalRotation;
                mat.Transpose();
                return mat;
            }
        }

        protected Vector3 TransFormLocalPosInverted
        {
            get
            {
                return _jointTransform.Translation;
            }
        }

        public Vector3 TransformWorldPos
        {
            get
            {
                SkeletonJoint b = ParentJoint;
                Vector3 v = TransFormLocalPosInverted;
                while (b != null)
                {
                    v = b.TransformLocalRotationTransposed.Transform(v);
                    b = b.ParentJoint;
                }
                if (ParentJoint != null) v += ParentJoint.TransformWorldPos;

                return v;
            }
        }

        public Matrix33 TransformWorldRotation
        {
            get
            {
                if (ParentJoint == null) return TransformLocalRotation;
                return ParentJoint.TransformWorldRotation * TransformLocalRotation;
            }
        }
        
        public Matrix44 JointTransformWorld
        {
            get
            {
                return new Matrix44(TransformWorldRotation, TransformWorldPos);
            }
        }
        
        #endregion

        public List<int> AffectedBlendIndices = new List<int>();

        public SkeletonJoint ParentJoint
        {
            get
            {
                if (ParentIndex == -1) return null;
                return _col[ParentIndex];
            }
        }

        public List<SkeletonJoint> ChildJoints
        {
            get
            {
                return new List<SkeletonJoint>(_col.Where(c => c.ParentIndex == Index));
            }
        }

        public bool IsAffectedJoint(int index)
        {
            SkeletonJoint p = ParentJoint;
            while (p != null)
            {
                if (p.Index == index) return true;
                p = p.ParentJoint;
            }
            return false;
        }

        public SkeletonJoint(int lodIndex, int index, int pindex, Skeleton col, Hash name, int lodFlags, Bounds bounds, TransformMatrix boundsTransform, TransformMatrix jointTransform)
        {
            _lodIndex = lodIndex;

            Index = index;
            ParentIndex = pindex;

            _col = col;

            Name = name;
            LodFlag = lodFlags;

            Bounds = bounds;

            _boundsTransform = boundsTransform;
            _jointTransform = jointTransform;
        }

        public override string ToString()
        {
            return Name.ToString();
        }
    }
}
