using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Decal.Interop.Core;
using Decal.Interop.Net;

namespace Decal.DecalNet
{
    [ComVisible(true)]
    [Guid("C8C406F8-BA2E-4964-8B04-FF38394A8E0E")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("DecalNet.NetService")]
    public class NetServiceImpl : INetService, IDecalService
    {
        internal static NetServiceImpl Instance { get; private set; }

        private IDecalCore _decalCore;
        private readonly List<INetworkFilter2> _filters = new List<INetworkFilter2>();

        public DecalCore Decal => (DecalCore)_decalCore;

        // Returns the network filter (V2 interface) if available
        public object Filter => _filters.Count > 0 ? _filters[0] : null;

        // Returns filter via IDispatch for VB compatibility
        public object FilterVB => Filter;

        public ACHooks Hooks => _decalCore?.Hooks;

        // IDecalService
        public void Initialize(DecalCore pDecal)
        {
            _decalCore = (IDecalCore)pDecal;
            Instance = this;

            // In native code: hooks recvfrom/sendto from wsock32.dll
            // Network hooking in C# will use the same approach via P/Invoke
            // or be handled by the native Inject.DLL shim
        }

        public void BeforePlugins()
        {
            // Load V1 network filters from registry
        }

        public void AfterPlugins()
        {
            // Remove V1 filters (after plugins had a chance to upgrade to V2)
        }

        public void Terminate()
        {
            // Terminate all filters
            foreach (var filter in _filters)
            {
                try { filter.Terminate(); } catch { }
            }
            _filters.Clear();
            _decalCore = null;

            if (Instance == this)
                Instance = null;
        }

        /// <summary>
        /// Register a V2 network filter.
        /// </summary>
        internal void RegisterFilter(INetworkFilter2 filter)
        {
            _filters.Add(filter);
            filter.Initialize((NetService)(object)this);
        }

        /// <summary>
        /// Dispatch a server-to-client message to all filters.
        /// Called from the network hook when a packet is received.
        /// </summary>
        internal void DispatchServerMessage(byte[] data)
        {
            var msg = new MessageImpl(data, false);
            foreach (var filter in _filters)
            {
                try { filter.DispatchServer((IMessage2)msg); } catch { }
            }
        }

        /// <summary>
        /// Dispatch a client-to-server message to all filters.
        /// Called from the network hook when a packet is sent.
        /// </summary>
        internal void DispatchClientMessage(byte[] data)
        {
            var msg = new MessageImpl(data, true);
            foreach (var filter in _filters)
            {
                try { filter.DispatchClient((IMessage2)msg); } catch { }
            }
        }
    }
}
