using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using AprsSharp.Parsers.Aprs;
using skyscraper5.Aprs.AprsSharp;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Ietf.Rfc768;
using skyscraper5.Ietf.Rfc971;

namespace skyscraper5.Aprs
{
    class AprsDecoder
    {
        public AprsDecoder(IAprsMessageReciever receiver)
        {
            this.receiver = receiver;
        }

        private IAprsMessageReciever receiver;

        public void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet)
        {
            UserDatagram userDatagram = new UserDatagram(ipv4Packet);
            MemoryStream ms = new MemoryStream(userDatagram.Payload, false);
            StreamReader sr = new StreamReader(ms, Encoding.ASCII);
            while (!sr.EndOfStream)
            {
                string? readLine = sr.ReadLine();
                Packet packet = null;
                try
                {
                    packet = new Packet(readLine);
                }
                catch (ArgumentException e)
                {
                    Debug.WriteLine("APRS Message decode failed: " + readLine);
                }
                
                if (packet != null)
                    ForwardToReceiver(packet);
            }
            sr.Close();
            ms.Close();
        }

        public void OnIpDatagram(int sourcePid, byte[] payload)
        {
            throw new NotImplementedException();
        }

        private void ForwardToReceiver(Packet packet)
        {
            InfoField packetInfoField = packet.InfoField;

            string name = packetInfoField.GetType().Name;
            switch (name)
            {
                case nameof(PositionInfo):
                    PositionInfo pi = (PositionInfo)packetInfoField;
                    receiver.OnAprsPosition(packet.Sender, pi.Position.Coordinates, pi.Comment);
                    break;
                case nameof(UnimplementedInfoField):
                    break;
                case nameof(WeatherInfo):
                    WeatherInfo wi = (WeatherInfo)packetInfoField;
                    receiver.OnAprsWeatherReport(packet.Sender, wi);
                    break;
                case nameof(MessageField):
                    MessageField message = (MessageField)packetInfoField;
                    receiver.OnAprsChatMessage(packet.Sender, packet.Path[0], message.RawMessage);
                    break;
                case nameof(StationCapabilities):
                    StationCapabilities stationCapabilities = (StationCapabilities)packetInfoField;
                    if (!stationCapabilities.IsIGate)
                        return;
                    receiver.OnAprsStationCapabilities(packet.Sender, stationCapabilities);
                    break;
                case nameof(WeatherReportInfoField):
                    WeatherReportInfoField weatherReportInfoField = (WeatherReportInfoField)packetInfoField;
                    receiver.OnAprsWeatherReport(packet.Sender, weatherReportInfoField.Wrapped);
                    break;
                case nameof(StatusInfo):
                    StatusInfo statusInfo = (StatusInfo)packetInfoField;
                    receiver.OnAprsPosition(packet.Sender, statusInfo.Position.Coordinates, statusInfo.Comment);
                    break;
                case nameof(RawGpsInfoField):
                    RawGpsInfoField rawGpsInfoField = (RawGpsInfoField)packetInfoField;
                    if (rawGpsInfoField.Parsed != null)
                        receiver.OnAprsGpsSentence(packet.Sender, rawGpsInfoField.Parsed);
                    break;
                default:
                    throw new NotImplementedException(name);
            }
        }
    }
}
