using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using YamlDotNet.Core.Tokens;

namespace Ethanol.MalwareSonar.Encoding
{
    /// <summary>
    /// Provides a utility for encoding an IP address.
    /// </summary>
    public static class EncodeIpAddress
    {
        /// <summary>
        /// Encodes the given IP address and prefix into a double representation.
        /// The method divides the integer representation of the IP by a value derived from the prefix.
        /// </summary>
        /// <remarks>
        /// The method encodes an IPv4 address into a double representation.
        /// The whole part of the double value represents the prefix of the IP address in its integer format. The fractional part captures the remainder of the IP address, ensuring that all parts of the IP are represented in the final double value.
        /// This representation allows for both the network and host portions of an IP address to be captured within a single floating-point number, providing a compact representation of the IP while retaining the distinction between its network and host parts.
        /// </remarks>
        /// <param name="ipAddress">The string representation of the IPv4 address.</param>
        /// <param name="prefix">The prefix length (CIDR notation) of the IP address.</param>
        /// <returns>A double value representing the encoded IP address.</returns>
        /// <exception cref="ArgumentException">Thrown when the input IP address format is invalid.</exception>
        public static double EncodeAsDouble(string ipAddress, int prefix)
        {
            // Validate if the given string is a correct IP address format.
            if (!System.Net.IPAddress.TryParse(ipAddress, out var ip))
            {
                throw new ArgumentException("Invalid IP address format.");
            }

            // Extract the individual octets of the IP address.
            byte[] octets = ip.GetAddressBytes();

            // Ensure the IP address has exactly 4 octets (IPv4).
            if (octets.Length != 4)
            {
                throw new ArgumentException("Invalid IP address format.");
            }

            // Calculate a mask based on the provided prefix length.
            uint mask = prefix >= 32 ? 1 : 0xFFFFFFFF >> prefix;

            // Convert the octets to a single uint representation of the IP address.
            var addr = (uint)(octets[0] << 24) | (uint)(octets[1] << 16) | (uint)(octets[2] << 8) | octets[3];

            // Encode the IP address as a double by dividing its integer representation by the mask.
            return (double)addr / mask;
        }
    }

}
