// TimezoneFileReader.cs
using System.IO.Compression;

namespace ReverseGeocode;

internal static class TimezoneFileReader
{
    private const int LineLength = 8;
    private const int LineEndLength = 1;

    private static readonly Lazy<MemoryStream> LazyData = new(LoadData);
    private static readonly Lazy<int> LazyCount = new(GetCount);


	private static MemoryStream LoadData()
    {
        var assembly = typeof(TimezoneFileReader).Assembly;
        using var compressedStream = assembly.GetManifestResourceStream("ReverseGeocode.TZ.txt.gz");
        using var stream = new GZipStream(compressedStream!, CompressionMode.Decompress);

        var ms = new MemoryStream();
        stream.CopyTo(ms);
        ms.Seek(0, SeekOrigin.Begin);
        return ms;
    }

    private static int GetCount() => (int) (LazyData.Value.Length / (LineLength + LineEndLength));

    public static int Count => LazyCount.Value;

    public static ReadOnlySpan<byte> GetGeohash(int line) => GetLine(line, 0, Geohash.Precision);

    public static int GetLineNumber(int line)
    {
        var digits = GetLine(line, Geohash.Precision, LineLength - Geohash.Precision);
        return GetDigit(digits[2]) + ((GetDigit(digits[1]) + (GetDigit(digits[0]) * 10)) * 10);
    }

    private static int GetDigit(byte b) => b - '0';

    private static ReadOnlySpan<byte> GetLine(int line, int start, int count)
    {
        var index = ((LineLength + LineEndLength) * (line - 1)) + start;
        var stream = LazyData.Value;

        return new ReadOnlySpan<byte>(stream.GetBuffer(), index, count);
    }
}
