//*************************************************************
//  Filename:       ByteArray.cs
//  Author:         MaesterRowen & Wondro (TeamFSD)
//  Date:           August 10, 2013
//  Description:    Class to help manage BigEndian byte array.
//*************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Collections;

namespace XuiWorkshop
{
    public class ByteArray : List<byte>
    {
        public long GetSize()
        {
            return Count;
        }
        public void AddDWORD(uint value)
        {
            // Split this unsigned int into 4 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 4);
            Array.Reverse(bytes, 0, 4);
            // Add each byte to our array
            foreach (byte b in bytes) Add(b);
        }
        public void AddWORD(ushort value)
        {
            // Split this unsigned short into 2 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 2);
            Array.Reverse(bytes, 0, 2);
            // Add each byte to our array
            foreach (byte b in bytes) Add(b);
        }
        public void AddBYTE(byte value)
        {
            // Add this singlar byte
            Add(value);
        }
        public void AddBOOL(bool value)
        {
            byte val = (byte)(value == true ? 0x1 : 0x0);
            Add(val);
        }
        public void AddFLOAT(float value)
        {
            // Split this unsigned int into 4 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 4);
            Array.Reverse(bytes, 0, 4);
            // Add each byte to our array
            foreach (byte b in bytes) Add(b);
        }
        public void AddCHAR(char value)
        {
            Add((byte)value);
        }
        public void AddSTRING(string value, bool addNull = true)
        {
            int stringPos = 0;
            while (stringPos < value.Length)
            {
                Add((byte)value[stringPos]);
                stringPos++;
            }
            // Write our NULL terminator
            if (addNull) Add((byte)0x00);
        }
        public void AddPackedDWORD(uint value)
        {
            // Check our upper range (65,279)
            if (value > (uint)0xEFF)
            {
                AddBYTE((byte)0xFF);
                AddDWORD((uint)value);
            }
            else if (value > (uint)0xEF)
            {
                uint highPart = value >> 8;
                highPart |= 0xF0;
                byte lowPart = (byte)(value & 0xFF);

                AddBYTE((byte)highPart);
                AddBYTE((byte)lowPart);
            }
            else
            {
                AddBYTE((byte)(value & 0xFF));
            }
        }
        public void AddByteARRAY(ByteArray byteArray)
        {
            foreach (byte b in byteArray)
            {
                AddBYTE(b);
            }
        }
        public void WriteToFile(System.IO.Stream stream)
        {
            foreach(byte b in this) 
                stream.WriteByte((byte)b);

            stream.Flush();
        }
        public void WriteToFile(System.IO.Stream stream, long pos)
        {
            // Grab our current position and store for later
            long currentPos = stream.Position;

            // Seek to requested position and write our byte array
            stream.Seek(pos, SeekOrigin.Begin);
            byte [] byteArray = ToArray();
            for (int x = 0; x < byteArray.Length; x++)
            {
                stream.WriteByte((byte)byteArray.GetValue(x));
            }
            stream.Flush();

            // Restore our file pos
            stream.Seek(currentPos, SeekOrigin.Begin);
        }

        // Update functions
        public void UpdateDWORD(uint value, long pos)
        {
            // Split this unsigned int into 4 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 4);
            Array.Reverse(bytes, 0, 4);

            // Update each byte to our array
            foreach (byte b in bytes)
            {
                this[(int)pos] = b;
                pos++;
            }
        }
        public void UpdateWORD(ushort value, long pos)
        {
            // Split this unsigned short into 2 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 2);
            Array.Reverse(bytes, 0, 2);

            // Update each byte to our array
            foreach (byte b in bytes)
            {
                this[(int)pos] = b;
                pos++;
            }
        }
        public void UpdateBYTE(byte value, long pos)
        {
            this[(int)pos] = value;
        }
        public void UpdateFLOAT(float value, long pos)
        {
            // Split this unsigned int into 4 bytes
            byte[] bytes = BitConverter.GetBytes(value);
            Debug.Assert(bytes.Length == 4);
            Array.Reverse(bytes, 0, 4);

            // Update each byte to our array
            foreach (byte b in bytes)
            {
                this[(int)pos] = b;
                pos++;
            }
        }
        public void UpdateCHAR(char value, long pos)
        {
            this[(int)pos] = (byte)value;
        }
    }
}
