//*************************************************************
//  Filename:       Xui.cs
//  Author:         MaesterRowen & Wondro (TeamFSD)
//  Date:           August 10, 2013
//  Description:    Helper structs/class for data in the XUI/XUR format.
//*************************************************************

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


namespace XuiWorkshop
{
    // Element Property Definitions
    public enum XUIELEM_PROP_TYPE {
        XUI_EPT_EMPTY,
        XUI_EPT_BOOL,
        XUI_EPT_INTEGER,
        XUI_EPT_UNSIGNED,
        XUI_EPT_FLOAT,
        XUI_EPT_STRING,
        XUI_EPT_COLOR,
        XUI_EPT_VECTOR,
        XUI_EPT_QUATERNION,
        XUI_EPT_OBJECT,
        XUI_EPT_CUSTOM
    }
    public struct XUIELEM_PROP_DEF
    {
        public uint Flags;
        public uint Index;
        public uint Offset;
        public uint Extra;
        public int Id;
        public string PropName;
        public XUIELEM_PROP_TYPE Type;
        public object DefaultVal;

        public List<XUIELEM_PROP_DEF> GetPropDefs()
        {
            if (PropName == "Fill")
                return XuiClass.Instance.GetFillPropArray();
            else if (PropName == "Stroke")
                return XuiClass.Instance.GetStrokePropArray();
            else if (PropName == "Gradient")
                return XuiClass.Instance.GetGradientPropArray();
            else
                return null;
        }
    }
    public struct XUI_CLASS
    {
        public string szClassName;
        public string szBaseClassName;
        public List<XUIELEM_PROP_DEF> PropDefs;
        public uint dwPropDefCount;
    }

    public class Xui
    {
        // Functions for reading data
        static public XUR8_HEADER _ReadHeader(BEBinaryReader xurReader)
        {
            // Read in our header
            XUR8_HEADER headerData;
            headerData.Magic = xurReader.ReadUInt32();
            headerData.Version = xurReader.ReadUInt32();
            headerData.Flags = xurReader.ReadUInt32();
            headerData.XuiVersion = xurReader.ReadUInt16();
            headerData.BinSize = xurReader.ReadUInt32();
            headerData.NumSections = xurReader.ReadUInt16();

            // Return our header
            return headerData;
        }
        static public XUR8_HEADER_INFO _ReadHeaderInfo(BEBinaryReader xurReader)
        {
            // Read in our header info
            XUR8_HEADER_INFO headerInfoData;
            headerInfoData.ObjectCount = _ReadPackedUlong(xurReader);
            headerInfoData.PropertyCount = _ReadPackedUlong(xurReader);
            headerInfoData.PropertyArrayCount = _ReadPackedUlong(xurReader);
            headerInfoData.CompoundObjectPropCount = _ReadPackedUlong(xurReader);
            headerInfoData.CompoundObjectPropArrayCount = _ReadPackedUlong(xurReader);
            headerInfoData.PropPathDepthCount = _ReadPackedUlong(xurReader);
            headerInfoData.TimelinePropPathCount = _ReadPackedUlong(xurReader);
            headerInfoData.SubTimelineCount = _ReadPackedUlong(xurReader);
            headerInfoData.KeyframePropCount = _ReadPackedUlong(xurReader);
            headerInfoData.KeyframeDataCount = _ReadPackedUlong(xurReader);
            headerInfoData.NamedFrameCount = _ReadPackedUlong(xurReader);
            headerInfoData.ObjectsWithChildrenCount = _ReadPackedUlong(xurReader);

            // Return our header info
            return headerInfoData;
        }
        static public List<string> _ReadStringTable(BEBinaryReader xurReader, ulong size)
        {
            List<string> stringTable = new List<string>();

            uint strLen = xurReader.ReadUInt32();
            ushort strCount = xurReader.ReadUInt16();

            string newString = "";
            char data = '\0';
            while (strCount > 0)
            {
                data = xurReader.ReadChar();
                if( data != '\0' ) newString += data.ToString();
                if (data == '\0')
                {
                    stringTable.Add(newString);
                    Console.WriteLine("Added " + newString + "\n");
                    strCount--;
                    newString = "";
                }
            }

            return stringTable;
        }

        static public List<XUIVECTOR> _ReadVectorTable(BEBinaryReader xurReader, ulong size)
        {
            List<XUIVECTOR> vectorTable = new List<XUIVECTOR>();
            ulong entries = size / 12;

            while (entries > 0)
            {
                XUIVECTOR vector;         
                vector.x = xurReader.ReadSingle();
                vector.y = xurReader.ReadSingle();
                vector.z = xurReader.ReadSingle();

                vectorTable.Add(vector);

                entries--;
            }

            return vectorTable;
        }

        static public List<XUIQUATERNION> _ReadQuaternionTable(BEBinaryReader xurReader, ulong size)
        {
            List<XUIQUATERNION> quatTable = new List<XUIQUATERNION>();
            ulong entries = size / 16;

            while (entries > 0)
            {
                XUIQUATERNION quat;
                quat.x = xurReader.ReadSingle();
                quat.y = xurReader.ReadSingle();
                quat.z = xurReader.ReadSingle();
                quat.w = xurReader.ReadSingle();

                quatTable.Add(quat);

                entries--;
            }

            return quatTable;
        }

        static public List<float> _ReadFloatTable(BEBinaryReader xurReader, ulong size)
        {
            List<float> floatTable = new List<float>();
            ulong entries = size / 4;

            while (entries > 0)
            {
                float fVal = xurReader.ReadSingle();
                floatTable.Add(fVal);

                entries--;
            }

            return floatTable;
        }

        static public List<XUICOLOR> _ReadColorTable(BEBinaryReader xurReader, ulong size)
        {
            List<XUICOLOR> colorTable = new List<XUICOLOR>();
            ulong entries = size / 4;

            while (entries > 0)
            {
                XUICOLOR colVal;
                colVal.argb = xurReader.ReadUInt32();
                colorTable.Add(colVal);
                entries--;
            }

            return colorTable;
        }

        static public uint _ReadPackedUlong(BEBinaryReader xurReader)
        {
            // Read the next byte in our stream
            uint firstVal = xurReader.ReadByte();
            
            uint finalResult = 0;
            if (firstVal != 0xFF) {
                if (firstVal < 0xF0) {
                    // Set this byte as our result
                    finalResult = firstVal;
                } else {
                    // Read the next byte and combine 
                    uint secondVal = xurReader.ReadByte();
                    uint highPart = (firstVal << 8) & 0xF00;
                    finalResult = highPart | secondVal;
                }
            } else {
                // Return the next 4 bytes
                finalResult = xurReader.ReadUInt32();
            }
            // Return result
            return finalResult;
        }
        static public byte _ReadByte( BEBinaryReader xurReader)
        {
            // Return byte
            return xurReader.ReadByte();
        }
        static public XUIELEM_PROP_TYPE _GetPropType(string type)
        {
            if (type == "string")
                return XUIELEM_PROP_TYPE.XUI_EPT_STRING;
            else if (type == "unsigned")
                return XUIELEM_PROP_TYPE.XUI_EPT_UNSIGNED;
            else if (type == "bool")
                return XUIELEM_PROP_TYPE.XUI_EPT_BOOL;
            else if (type == "color")
                return XUIELEM_PROP_TYPE.XUI_EPT_COLOR;
            else if (type == "float")
                return XUIELEM_PROP_TYPE.XUI_EPT_FLOAT;
            else if (type == "vector")
                return XUIELEM_PROP_TYPE.XUI_EPT_VECTOR;
            else if (type == "integer")
                return XUIELEM_PROP_TYPE.XUI_EPT_INTEGER;
            else if (type == "quaternion")
                return XUIELEM_PROP_TYPE.XUI_EPT_QUATERNION;
            else if (type == "object")
                return XUIELEM_PROP_TYPE.XUI_EPT_OBJECT;
            else if (type == "custom")
                return XUIELEM_PROP_TYPE.XUI_EPT_CUSTOM;
            else
                return XUIELEM_PROP_TYPE.XUI_EPT_EMPTY;
        }

        static public uint _GetFlagType(string flags)
        {
            string[] flagArray = flags.Split('|');
            uint ret = 0;

            foreach (string flag in flagArray)
            {
                if (flag == "indexed")
                    ret += 0x1;
            }

            return ret;
        }
    }
}
