using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AprsSharp.Parsers.Aprs;

namespace skyscraper5.Aprs.AprsSharp
{
    class WeatherReportInfoField : InfoField
    {
        public WeatherReportInfoField(string rawMsg)
        {
            Comment = rawMsg;
            WindDirection = GetWeatherMeasurement('^');
            WindSpeed = GetWeatherMeasurement('/');
            WindGust = GetWeatherMeasurement('g');
            Temperature = GetWeatherMeasurement('t');
            Rainfall1Hour = GetWeatherMeasurement('r');
            Rainfall24Hour = GetWeatherMeasurement('p');
            RainfallSinceMidnight = GetWeatherMeasurement('P');
            Humidity = GetWeatherMeasurement('h', 2);
            BarometricPressure = GetWeatherMeasurement('b', 5);
            Luminosity = GetWeatherMeasurement('L') ?? GetWeatherMeasurement('l') + 1000;
            RainRaw = GetWeatherMeasurement('#');
            Snow = GetWeatherMeasurement('s');

            string ogMsg = rawMsg;
            int indexOf = ogMsg.IndexOf(' ') - 1;
            for (int i = indexOf; i > 0; i--)
            {
                char c = ogMsg[i];
                if (Char.IsDigit(c) || c == '.' || c == ' ')
                {
                    indexOf = i;
                    break;
                }
            }

            indexOf++;
            Comment = ogMsg.Substring(indexOf);

            Wrapped = new WeatherInfo(null, false, null, Comment, WindDirection, WindSpeed, WindGust,
                Temperature, Rainfall1Hour, Rainfall24Hour, RainfallSinceMidnight, Humidity, BarometricPressure,
                Luminosity, RainRaw, Snow);
            Wrapped.Comment = Comment;
        }

        private int? Snow { get; set; }

        private int? RainRaw { get; set; }

        private int? Luminosity { get; set; }

        private int? BarometricPressure { get; set; }

        private int? Humidity { get; set; }

        private int? RainfallSinceMidnight { get; set; }

        private int? Rainfall24Hour { get; set; }

        private int? Rainfall1Hour { get; set; }

        private int? Temperature { get; set; }

        private int? WindGust { get; set; }

        private int? WindSpeed { get; set; }

        private int? WindDirection { get; set; }

        private string Comment { get; set; }

        private int? GetWeatherMeasurement(char measurementKey, int length = 3)
        {
            // Regex below looks for the measurement key followed by either `length` numbers
            // or a negative number of `length - 1` digits (to allow for the negative sign)
            var match = Regex.Match(Comment, $"{measurementKey}(([0-9]{{{length}}})|(-[0-9]{{{length - 1}}}))");
            return match.Success ? int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture) : null;
        }

        public WeatherInfo Wrapped { get; private set; }
        public override string Encode()
        {
            throw new NotSupportedException();
        }
    }
}
