﻿/*
 * 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()));
    }
}
