using System;
using System.IO;

namespace Oni
{
    internal sealed class InstanceFileHeader
    {
        public const long OniPCTemplateChecksum = 0x0003bcdf33dc271f;
        public const long OniMacTemplateChecksum = 0x0003bcdf23c13061;
        public const int Version31 = 0x56523331;
        public const int Version32 = 0x56523332;
        public const long Signature = 0x0008001000140040;

        #region Private data
        private long templateChecksum;
        private int version;
        private long signature;
        private int instanceCount;
        private int nameCount;
        private int templateCount;
        private int dataTableOffset;
        private int dataTableSize;
        private int nameTableOffset;
        private int nameTableSize;
        private int rawTableOffset;
        private int rawTableSize;
        #endregion

        internal static InstanceFileHeader Read(BinaryReader reader)
        {
            var header = new InstanceFileHeader
            {
                templateChecksum = reader.ReadInt64(),
                version = reader.ReadInt32(),
                signature = reader.ReadInt64()
            };

            ValidateHeader(header);

            header.instanceCount = reader.ReadInt32();
            header.nameCount = reader.ReadInt32();
            header.templateCount = reader.ReadInt32();
            header.dataTableOffset = reader.ReadInt32();
            header.dataTableSize = reader.ReadInt32();
            header.nameTableOffset = reader.ReadInt32();
            header.nameTableSize = reader.ReadInt32();

            if (header.version == Version32)
            {
                header.rawTableOffset = reader.ReadInt32();
                header.rawTableSize = reader.ReadInt32();

                reader.Skip(8);
            }
            else
            {
                reader.Skip(16);
            }

            return header;
        }

        private static void ValidateHeader(InstanceFileHeader header)
        {
            if (header.templateChecksum != OniPCTemplateChecksum && header.templateChecksum != OniMacTemplateChecksum)
            {
                header.templateChecksum = OniMacTemplateChecksum;
                //throw new InvalidDataException("Invalid template checksum");
            }

            if (header.version != Version31 && header.version != Version32)
                throw new InvalidDataException("Unknown file version");

            if (header.version == Version31 && header.signature != Signature)
                throw new InvalidDataException("Invalid file signature");
        }

        public long TemplateChecksum => templateChecksum;
        public int Version => version;
        public int InstanceCount => instanceCount;
        public int NameCount => nameCount;
        public int TemplateCoun => templateCount;
        public int DataTableOffset => dataTableOffset;
        public int DataTableSize => dataTableSize;
        public int NameTableOffset => nameTableOffset;
        public int NameTableSize => nameTableSize;
        public int RawTableOffset => rawTableOffset;
        public int RawTableSize => rawTableSize;
    }
}
