using CommonAI.Zone.ZoneEditor;
using CommonLang.IO;
using ET;
using System;
using System.Collections.Generic;
using System.IO;

public class SceneDataLoader : ISceneDataLoader
{
    public struct FileOffset
    {
        internal int position;
        internal int len;
    }

    static SceneData LoadFromStream(Stream stream, bool client_data, IExternalizableFactory factory)
    {
        var input = new InputStream(stream, factory);
        int typeID = input.GetS32();
        Type type = factory.GetType(typeID);
        if (typeof(SceneData).Equals(type))
        {
            var info = new SceneData();
            if (client_data)
            {
                info.ReadExternalByClient(input);
            }
            else
            {
                info.ReadExternal(input);
            }
            return info;
        }
        else
        {
            Log.Error($"scene ex data read type({type}) error");
        }
        return null;
    }

    private readonly MemoryStream binDataStream;

    private readonly Dictionary<string, FileOffset> filesDic;

    public SceneDataLoader(byte[] binData)
    {
        if (binData == null)
        {
            binDataStream = null;
            return;
        }
        binDataStream = new MemoryStream(binData);
        filesDic = new Dictionary<string, FileOffset>();

        var br = new BinaryReader(binDataStream);
        var count = br.ReadInt32();
        var names = new string[count];
        var sizes = new int[count];

        for (int i = 0; i < count; i++)
        {
            names[i] = br.ReadString();
            sizes[i] = br.ReadInt32();
        }
        var offset = (int)binDataStream.Position;
        for (int i = 0; i < count; i++)
        {
            filesDic[names[i]] = new FileOffset() { position = offset, len = sizes[i] };
            offset += sizes[i];
        }
    }

    private readonly MemoryStream msSceneDataCache = new MemoryStream();
    private int preSceneDataId = 0;
    public SceneData Load(int sceneId, bool client_data, IExternalizableFactory factory)
    {
        if (binDataStream == null)
        {
            return null;
        }
        if (sceneId != preSceneDataId)
        {
            FileOffset fileOffset;
            if (!filesDic.TryGetValue(sceneId.ToString(), out fileOffset))
            {
                return null;
            }
            binDataStream.Position = fileOffset.position;
            msSceneDataCache.Position = 0;
            //LZMAHelper.Decompress(binDataStream, fileOffset.len, msSceneDataCache);
            binDataStream.CopyTo(msSceneDataCache, fileOffset.len);
            preSceneDataId = sceneId;
        }
        msSceneDataCache.Position = 0;
        var sd = LoadFromStream(msSceneDataCache, client_data, factory);
        return sd;
    }
}