using System;

using Multiplayer.API;
using Multiplayer.Common;

namespace Multiplayer.Client
{
    public class ReadingSyncWorker(ByteReader reader, SyncSerialization serialization) : SyncWorker(false)
    {
        internal readonly ByteReader reader = reader;
        readonly int initialPos = reader.Position;

        public ByteReader Reader => reader;

        public override void Bind<T>(ref T obj, SyncType type)
        {
            obj = (T)serialization.ReadSyncObject(reader, type);
        }

        public override void Bind<T>(ref T obj)
        {
            obj = (T)serialization.ReadSyncObject(reader, typeof(T));
        }

        public override void Bind(object obj, string name)
        {
            object value = MpReflection.GetValue(obj, name);

            Type type = value.GetType();
            var res = serialization.ReadSyncObject(reader, type);
            MpReflection.SetValue(obj, name, res);
        }

        public override void Bind(ref byte obj)
        {
            obj = reader.ReadByte();
        }

        public override void Bind(ref sbyte obj)
        {
            obj = reader.ReadSByte();
        }

        public override void Bind(ref short obj)
        {
            obj = reader.ReadShort();
        }

        public override void Bind(ref ushort obj)
        {
            obj = reader.ReadUShort();
        }

        public override void Bind(ref int obj)
        {
            obj = reader.ReadInt32();
        }

        public override void Bind(ref uint obj)
        {
            obj = reader.ReadUInt32();
        }

        public override void Bind(ref long obj)
        {
            obj = reader.ReadLong();
        }

        public override void Bind(ref ulong obj)
        {
            obj = reader.ReadULong();
        }

        public override void Bind(ref float obj)
        {
            obj = reader.ReadFloat();
        }

        public override void Bind(ref double obj)
        {
            obj = reader.ReadDouble();
        }

        public override void Bind(ref bool obj)
        {
            obj = reader.ReadBool();
        }

        public override void Bind(ref string? obj)
        {
            obj = reader.ReadStringNullable();
        }

        public override void BindType<T>(ref Type type)
        {
            type = serialization.TypeHelper.GetImplementationByIndex(typeof(T), reader.ReadUShort());
        }

        internal void Reset()
        {
            reader.Seek(initialPos);
        }
    }
}
