using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mafia2Tool.DataFormats;
using Gibbed.Illusion.FileFormats;
using System.IO;
using Mafia2Tool.DataFormats.FrameResources;
using Gibbed.Illusion.FileFormats.ResourceTypes;

namespace Mafia2Tool.Parsed
{
    public class MeshParser
    {
        public FrameResource _frameResource;
        public List<VertexBufferPool> _vertexBufferPools;
        public List<IndexBufferPool> _indexBufferPools;

        public Dictionary<ulong, TextureResource> _textures;

        public List<Collisions> _collisions;

        public MeshParser(string sdsFilename)
        {
            LoadSDS(sdsFilename);
        }

        public void LoadSDS(string sdsFilename)
        {
            var reader = new SdsReader();
            reader.Open(sdsFilename);

            SdsMemory Archive = reader.LoadToMemory();
            reader.Close();

            var frType = Archive.ResourceTypes.SingleOrDefault(c => c.Name == "FrameResource");
            var ibpType = Archive.ResourceTypes.SingleOrDefault(c => c.Name == "IndexBufferPool");
            var vbpType = Archive.ResourceTypes.SingleOrDefault(c => c.Name == "VertexBufferPool");

            if (frType != null && ibpType != null && vbpType != null)
            {
                var frps = new List<SdsMemory.Entry>(Archive.Entries.Where(c => c.TypeId == frType.Id));
                var ibps = new List<SdsMemory.Entry>(Archive.Entries.Where(c => c.TypeId == ibpType.Id));
                var vbps = new List<SdsMemory.Entry>(Archive.Entries.Where(c => c.TypeId == vbpType.Id));

                foreach (var e in frps)
                {
                    e.Data.Position = 0;
                    _frameResource = new FrameResource(new BinaryReader(e.Data));
                }

                _indexBufferPools = new List<IndexBufferPool>();
                foreach (var e in ibps)
                {
                    e.Data.Position = 0;
                    IndexBufferPool pool = new IndexBufferPool(new BinaryReader(e.Data));
                    _indexBufferPools.Add(pool);
                }

                _vertexBufferPools = new List<VertexBufferPool>();
                foreach (var e in vbps)
                {
                    e.Data.Position = 0;
                    VertexBufferPool pool = new VertexBufferPool(new BinaryReader(e.Data));
                    _vertexBufferPools.Add(pool);
                }
            }
            
            loadTextures(Archive);
            loadCollisions(Archive);
        }

        private void loadTextures(SdsMemory Archive)
        {
            var texType = Archive.ResourceTypes.SingleOrDefault(c => c.Name == "Texture");
            if (texType != null)
            {
                var textureEntries = new List<SdsMemory.Entry>(Archive.Entries.Where(c => c.TypeId == texType.Id));
                if(_textures == null) _textures = new Dictionary<ulong, TextureResource>();
                foreach (var e in textureEntries)
                {
                    var resource = new TextureResource();
                    resource.Deserialize(e.Header, e.Data);
                    _textures.Add(resource.NameHash, resource);
                }
            }
        }

        private void loadCollisions(SdsMemory Archive)
        {
            var colType = Archive.ResourceTypes.SingleOrDefault(c => c.Name == "Collisions");
            if (colType != null)
            {
                var colEntries = new List<SdsMemory.Entry>(Archive.Entries.Where(c => c.TypeId == colType.Id));
                if (_collisions == null) _collisions = new List<Collisions>();
                foreach (var e in colEntries)
                {
                    e.Data.Position = 0;
                    Collisions cs = new Collisions(new BinaryReader(e.Data));
                    _collisions.Add(cs);
                }
            }
        }

        public Model GetModel(SingleMeshComponent component)
        {
            return new Mafia2Tool.Parsed.Model(component, _vertexBufferPools, _indexBufferPools);
        }
    }
}
