﻿/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace DotPulsar.Internal.Compression;

using DotPulsar.Exceptions;
using DotPulsar.Internal.Abstractions;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

public static class ZstdCompression
{
    public delegate byte[] Wrap(byte[] src);
    public delegate int Unwrap(byte[] src, byte[] dst, int offset, bool bufferSizePrecheck);

    public static bool TryLoading(out ICompressorFactory? compressorFactory, out IDecompressorFactory? decompressorFactory)
    {
        try
        {
            var assembly = Assembly.Load("ZstdNet");

            var definedTypes = assembly.DefinedTypes.ToArray();

            var decompressorType = Find(definedTypes, "ZstdNet.Decompressor");
            var decompressorMethods = decompressorType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            var unwrapMethod = FindUnwrap(decompressorMethods);

            var compressorType = Find(definedTypes, "ZstdNet.Compressor");
            var compressorMethods = compressorType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            var wrapMethod = FindWrap(compressorMethods);

            compressorFactory = new CompressorFactory(PulsarApi.CompressionType.Zstd, () =>
            {
                var compressor = Activator.CreateInstance(compressorType);
                if (compressor is null)
                    throw new Exception($"Activator.CreateInstance returned null when trying to create a {compressorType.FullName}");

                var wrap = (Wrap) wrapMethod.CreateDelegate(typeof(Wrap), compressor);
                return new Compressor(CreateCompressor(wrap), (IDisposable) compressor);
            });

            decompressorFactory = new DecompressorFactory(PulsarApi.CompressionType.Zstd, () =>
            {
                var decompressor = Activator.CreateInstance(decompressorType);
                if (decompressor is null)
                    throw new Exception($"Activator.CreateInstance returned null when trying to create a {decompressorType.FullName}");

                var unwrap = (Unwrap) unwrapMethod.CreateDelegate(typeof(Unwrap), decompressor);
                return new Decompressor(CreateDecompressor(unwrap), (IDisposable) decompressor);
            });

            return true;
        }
        catch
        {
            // Ignore
        }

        compressorFactory = null;
        decompressorFactory = null;

        return false;
    }

    private static TypeInfo Find(IEnumerable<TypeInfo> types, string fullName)
    {
        foreach (var type in types)
        {
            if (type.FullName is null || !type.FullName.Equals(fullName))
                continue;

            if (type.IsPublic &&
                type.IsClass &&
                !type.IsAbstract &&
                type.ImplementedInterfaces.Contains(typeof(IDisposable)) &&
                type.GetConstructor(Type.EmptyTypes) is not null)
                return type;

            break;
        }

        throw new Exception($"{fullName} as a public class with an empty public constructor and implementing IDisposable was not found");
    }

    private static MethodInfo FindWrap(MethodInfo[] methods)
    {
        const string name = "Wrap";

        foreach (var method in methods)
        {
            if (method.Name != name || method.ReturnType != typeof(byte[]))
                continue;

            var parameters = method.GetParameters();
            if (parameters.Length != 1)
                continue;

            if (parameters[0].ParameterType != typeof(byte[]))
                continue;

            return method;
        }

        throw new Exception($"A method with the name '{name}' matching the delegate was not found");
    }

    private static MethodInfo FindUnwrap(MethodInfo[] methods)
    {
        const string name = "Unwrap";

        foreach (var method in methods)
        {
            if (method.Name != name || method.ReturnType != typeof(int))
                continue;

            var parameters = method.GetParameters();
            if (parameters.Length != 4)
                continue;

            if (parameters[0].ParameterType != typeof(byte[]) ||
                parameters[1].ParameterType != typeof(byte[]) ||
                parameters[2].ParameterType != typeof(int) ||
                parameters[3].ParameterType != typeof(bool))
                continue;

            return method;
        }

        throw new Exception($"A method with the name '{name}' matching the delegate was not found");
    }

    private static Func<ReadOnlySequence<byte>, int, ReadOnlySequence<byte>> CreateDecompressor(Unwrap decompress)
    {
        return (source, size) =>
        {
            var decompressed = new byte[size];
            var bytesDecompressed = decompress(source.ToArray(), decompressed, 0, false);
            if (size == bytesDecompressed)
                return new ReadOnlySequence<byte>(decompressed);

            throw new CompressionException($"ZstdNet.Decompressor returned {bytesDecompressed} but expected {size}");
        };
    }

    private static Func<ReadOnlySequence<byte>, ReadOnlySequence<byte>> CreateCompressor(Wrap compress)
        => (source) => new ReadOnlySequence<byte>(compress(source.ToArray()));
}
