//*************************************************************
//  Filename:       XuiStructs.cs
//  Author:         MaesterRowen & Wondro (TeamFSD)
//  Date:           August 10, 2013
//  Description:    Structs used in the XUI/XUR format.
//*************************************************************

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

namespace XuiWorkshop
{
    // XUI Specific Variable Type
    public struct XUIPOINT
    {
        public float x;
        public float y;
    }
    public struct XUIVECTOR
    {
        public float x;
        public float y;
        public float z;
        public override bool Equals(object obj)
        {
            XUIVECTOR vec = (XUIVECTOR)obj;
            if (x != vec.x) return false;
            if (y != vec.y) return false;
            if (z != vec.z) return false;

            return true;
        }
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Clear();
            builder.AppendFormat("{0:f6},{1:f6},{2:f6}", x,y,z);
            return builder.ToString();
        }
    }
    public struct XUIQUATERNION
    {
        public float x;
        public float y;
        public float z;
        public float w;
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Clear();
            builder.AppendFormat("{0:f6},{1:f6},{2:f6},{3:f6}", x, y, z, w);
            return builder.ToString();
        }
    }
    public struct XUICOLOR
    {
        public uint argb;
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Clear();
            builder.AppendFormat("0x{0:x8}", argb);
            return builder.ToString();
        }
    }
    public struct XUIBEZIERPOINT 
    {
        public XUIPOINT vecPoint;
        public XUIPOINT vecCtrl1;
        public XUIPOINT vecCtrl2;
    }
    public class XUICUSTOM
    {
        public uint Offset;
        public uint DataLen;
        public XUIPOINT BoundingBox;
        public uint NumPoints;
        public List<XUIBEZIERPOINT> Points;
        public XUICUSTOM() 
        {
            DataLen = 0;
            BoundingBox.x = 0; BoundingBox.y = 0;
            NumPoints = 0;
            Points = new List<XUIBEZIERPOINT>();
            Offset = 0;
        }
        public ByteArray ToBinary()
        {
            ByteArray byteArray = new ByteArray();

            byteArray.AddDWORD(DataLen);
            byteArray.AddFLOAT(BoundingBox.x);
            byteArray.AddFLOAT(BoundingBox.y);
            byteArray.AddDWORD(NumPoints);

            foreach (XUIBEZIERPOINT pt in Points)
            {
                byteArray.AddFLOAT(pt.vecPoint.x);
                byteArray.AddFLOAT(pt.vecPoint.y);
                byteArray.AddFLOAT(pt.vecCtrl1.x);
                byteArray.AddFLOAT(pt.vecCtrl1.y);
                byteArray.AddFLOAT(pt.vecCtrl2.x);
                byteArray.AddFLOAT(pt.vecCtrl2.y);
            }

            return byteArray;
        }
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Clear();
            builder.AppendFormat("{0},", NumPoints);
            foreach (XUIBEZIERPOINT pt in Points)
            {
                builder.AppendFormat("{0:f6},{1:f6},{2:f6},{3:f6},{4:f6},{5:f6},0,",
                    pt.vecPoint.x, pt.vecPoint.y,
                    pt.vecCtrl1.x, pt.vecCtrl1.y,
                    pt.vecCtrl2.x, pt.vecCtrl2.y
                );
            }
            return builder.ToString();
        }
    }
    public struct XUIOBJECT
    {
        public uint data;
    }
    public struct XUINAMEDFRAMEDATA
    {
        public uint NameStringIndex;
        public string Name;
        public uint Time;
        public XUI_NAMEDFRAME_COMMAND Command;
        public uint TargetStringIndex;
        public string Target;
        public override bool Equals(object obj)
        {
            XUINAMEDFRAMEDATA data = (XUINAMEDFRAMEDATA)obj;
            if (NameStringIndex != data.NameStringIndex) return false;
            if (Name != data.Name) return false;
            if (Time != data.Time) return false;
            if (Command != data.Command) return false;
            if (TargetStringIndex != data.TargetStringIndex) return false;
            if (Target != data.Target) return false;
            return true;
        }
    }
    public struct XUIKEYFRAMEPROPDATA
    {
        public uint PropertyIndex;
    }
    public class XUIKEYFRAMEDATA
    {
        public uint Frame;
        public uint Flags;
        public XUI_INTERPOLATE InterpolateType;
        public uint Unknown1;
        public byte EaseIn;
        public byte EaseOut;
        public byte EaseScale;
        public uint KeyframePropIdx;
        public List<XUIPROPERTYDATA> PropList;
        public uint VectorIdx;
        public XUIVECTOR VectorRef;
        public override bool Equals(object obj)
        {
            XUIKEYFRAMEDATA data = (XUIKEYFRAMEDATA)obj;

            if (Frame != data.Frame) return false;
            if (Flags != data.Flags) return false;
            if (InterpolateType != data.InterpolateType) return false;
            if (Unknown1 != data.Unknown1) return false;
            if (EaseIn != data.EaseIn) return false;
            if (EaseOut != data.EaseOut) return false;
            if (EaseScale != data.EaseScale) return false;
            if (KeyframePropIdx != data.KeyframePropIdx) return false;
            if (VectorIdx != data.VectorIdx) return false;
            if (VectorRef.Equals(data.VectorRef) == false) return false;

            return true;
        }
        public XUIKEYFRAMEDATA()
        {
            InterpolateType = XUI_INTERPOLATE.XUI_INTERPOLATE_LINEAR;
            Frame = 0;
            Flags = 0;
            Unknown1 = 0;
            EaseIn = 0;
            EaseOut = 0;
            EaseScale = 0;
            KeyframePropIdx = 0;
            PropList = new List<XUIPROPERTYDATA>();
            VectorIdx = 0;
            VectorRef = new XUIVECTOR();
        }
    }

    public class XUIOBJECTDATA
    {
        public uint ObjectId;
        public string ClassName;
        public uint Flags;
        public List<XUIPROPERTYDATA> PropertyArray;
        public List<XUIOBJECTDATA> ChildrenArray;
        public uint NumNamedFrames;
        public List<XUINAMEDFRAMEDATA> NamedFrameArray;
        public uint NumSubTimelines;
        public List<XUISUBTIMELINEDATA> SubTimelines;
        public string HeriarchyId;

        public object GetPropVal(string propId)
        {
            foreach (XUIPROPERTYDATA prop in PropertyArray)
            {
                if (prop.PropDef.PropName == propId)
                    return prop.PropValue;
            }
            // Property Not Found
            return "";
        }
        public XUIOBJECTDATA GetObjectByHeriarchyId(string Id)
        {
            XUIOBJECTDATA temp = new XUIOBJECTDATA();

            if (HeriarchyId == Id)
                return this;
            else
            {
                foreach (XUIOBJECTDATA child in ChildrenArray)
                {
                    temp = child.GetObjectByHeriarchyId(Id);
                    
                    // Make sure we are in the correct item
                    if (temp != null)
                    {
                       return temp;
                    }
                }
            }

            return null;
        }
        public void SetPropVal(string propId, object propVal)
        {
            for (int i = 0; i < this.PropertyArray.Count; i++)
            {
                XUIPROPERTYDATA tmp = PropertyArray[i];
                if (tmp.PropDef.PropName == propId)
                    tmp.PropValue = propVal;
            }
        }
        public void AddPropVal(string propId, object propVal)
        {
            XUIPROPERTYDATA tmp = new XUIPROPERTYDATA();
            XUIELEM_PROP_DEF tmpDef = XuiClass.Instance.FindProperty(propId, this.ClassName);

            tmp.PropType = tmpDef.Type;
            tmp.Flags = tmpDef.Flags | 0x100;
            tmp.Index = 0; // Indexed props currently not supported (TODO)
            tmp.PropDef = tmpDef;
            tmp.PropValue = propVal;

            PropertyArray.Add(tmp);
        }
        public bool IsIgnored()
        {
            // Check if this class needs its special properties written to an EXT file
            if (Array.IndexOf(Global.ignoreClasses, ClassName) > -1)
                return true;
            else
                return false;
        }
        public XUIOBJECTDATA()
        {
            ObjectId = 0;
            ClassName = "";
            Flags = 0;
            PropertyArray = new List<XUIPROPERTYDATA>();
            ChildrenArray = new List<XUIOBJECTDATA>();
            NumNamedFrames = 0;
            NamedFrameArray = new List<XUINAMEDFRAMEDATA>();
            NumSubTimelines = 0;
            SubTimelines = new List<XUISUBTIMELINEDATA>();
            HeriarchyId = "";
        }
    }


    public class XUIPROPERTYDATA
    {
        public uint Flags;
        public uint Index;
        public uint CompoundPropId;
        public object PropValue { get; set; }
        public XUIELEM_PROP_TYPE PropType;
        public XUIELEM_PROP_DEF PropDef { get; set; }

        public XUIPROPERTYDATA()
        {
            Flags = 0;
            Index = 0;
            CompoundPropId = 0;
            PropType = XUIELEM_PROP_TYPE.XUI_EPT_EMPTY;
        }
    }
    public class XUICOMPOUNDPROPDATA
    {
        public uint Index;
        public List<XUIPROPERTYDATA> PropertyArray;
        public XUICOMPOUNDPROPDATA()
        {
            Index = 0;
            PropertyArray = new List<XUIPROPERTYDATA>();
        }
    }
    public class XUITIMELINEPROPPATH
    {
        public uint Flags;
        public uint Depth;
        public uint Index;
        public List<XUIELEM_PROP_DEF> PropDefArray;
        public XUITIMELINEPROPPATH()
        {
            Flags = 0;
            Depth = 0;
            Index = 0;
            PropDefArray = new List<XUIELEM_PROP_DEF>();
        }
    }
    public class XUISUBTIMELINEDATA
    {
        public uint ElementStringIdx;
        public string ElementId;
        public uint Flags;
        public uint NumPropPaths;
        public List<XUITIMELINEPROPPATH> PropPathArray;
        public List<uint> IndexArray;
        public List<XUIKEYFRAMEDATA> KeyframeDataArray;
        public ArrayList PropValueArray;
        public XUISUBTIMELINEDATA()
        {
            ElementStringIdx = 0;
            ElementId = "";
            Flags = 0;
            NumPropPaths = 0;
            PropPathArray = new List<XUITIMELINEPROPPATH>();
            IndexArray = new List<uint>();
            KeyframeDataArray = new List<XUIKEYFRAMEDATA>();
            PropValueArray = new ArrayList();
        }
    }

    // XURv8 Structs
    public struct XUR8_HEADER
    {
        public uint Magic;
        public uint Version;
        public uint Flags;
        public ushort XuiVersion;
        public uint BinSize;
        public ushort NumSections;
    }
    public struct XUR8_HEADER_INFO
    {
        public uint ObjectCount;                    // 100% correct
        public uint PropertyCount;                  // 100% correct
        public uint PropertyArrayCount;             // 100% correct
        public uint CompoundObjectPropCount;        //  50% correct          
        public uint CompoundObjectPropArrayCount;   // 100% correct   
        public uint PropPathDepthCount;             // 100% correct
        public uint TimelinePropPathCount;          // 100% correct
        public uint SubTimelineCount;               // 100% correct
        public uint KeyframePropCount;              // 100% correct
        public uint KeyframeDataCount;              // 100% correct
        public uint NamedFrameCount;                // 100% correct
        public uint ObjectsWithChildrenCount;       //  50% correct
    }
    public struct XUR8_SECTION
    {
        public uint Name;
        public uint Offset;
        public uint Size;
        public override string ToString()
        {
            return Name.ToString("X8");
        }
    }
    public enum XUR8_SECTION_NAME
    {
        SECTION_KEYD,
        SECTION_COLR,
        SECTION_CUST,
        SECTION_DATA,
        SECTION_DBUG,
        SECTION_FLOT,
        SECTION_KEYP,
        SECTION_NAME,
        SECTION_QUAT,
        SECTION_STRN,
        SECTION_VECT,
        SECTION_COUNT,
    }
}
