using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PhilExample.Interfaces;
using PhilExample.Services;
using PhilExampleCrawler.Common.Models;
using PhilExampleCrawler.Common.TCP.Enums;
using PhilExampleCrawler.Common.TCP.Packets;
using PhilExampleCrawler.Common.TCP.Utils;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace PhilExample
{
    /// <summary>
    /// Test page for TCP Implementation, not in use
    /// </summary>
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class TCPPage : ContentPage
    {
        private readonly ICrawlService_CH _crawler = DependencyService.Get<ICrawlService_CH>();
        private readonly ITCPClient _tcpClient = DependencyService.Get<ITCPClient>();
        private readonly IInsertionNotificationService _notiService = DependencyService.Get<IInsertionNotificationService>();

        public TCPPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
        }

        private async void OnConnect_Clicked(object sender, EventArgs e)
        {
            var user = await _crawler.LoginAsync(_entry_AuthCode.Text).ConfigureAwait(false);
            if (user == null)
                return;

            if (!_tcpClient.ConnectToServer(App.TCPSERVER_IP, App.TCPSERVER_PORT))
                return;

            if (!_tcpClient.RegisterForUpdates(user))
                return;

            if (!_tcpClient.IsUserRegistered || !_tcpClient.RegisteredUntil.HasValue || _tcpClient.RegisteredUntil.Value < DateTime.Now)
                return;

            var crawlSessions = await _crawler.GetCrawlSessionsAsync(user.ID);
            App.CurrentSession = new UserSession(-1, user, crawlSessions, _tcpClient.RegisteredUntil.Value);

            _tcpClient.OnDataReceived += TCPClient_OnDataReceived;

            //Update UI
            Device.BeginInvokeOnMainThread(() =>
            {
                _Layi.Children.Add(new Label() { Text = "Du bist connected als '" + user.AuthCode + "'", TextColor = Color.LightBlue });
            });

            UpdateUI(crawlSessions);
        }

        private async void OnDisconnect_Clicked(object sender, EventArgs e)
        {
            //_tcpClient.Unregister(App.CurrentSession.User);
            _tcpClient.Disconnect();
            await _crawler.LogoutAsync();
        }

        private int id = 0;
        private void TCPClient_OnDataReceived(object sender, (int connectionID, BasePacket bp) e)
        {
            if (e.bp.LoadData.Type == LoadType.NewInsertionLoad && e.bp.LoadData is NewInsertionLoad newInsertion)
            {
                //Notification & GUI Update
                _notiService.PublishNotification(GetTimeStamp() + " neue anzeige: ", newInsertion.Href, ++id > 5 ? (id = 1) : id);
                Device.BeginInvokeOnMainThread(() =>
                {
                    _Layi.Children.Add(new Label() { Text = newInsertion.Href, TextColor = Color.OrangeRed });
                });
            }
        }


        /// <summary> TODO: Make TCP API recognize that a new CrawlSession was added  </summary>
        private async void OnSendParams_Clicked(object sender, EventArgs e)
        {
            var newSess = await _crawler.RegisterCrawlSessionAsync(App.CurrentSession.User.ID, new CrawlSearchParams(_entry_Keywords.Text,
                                                                                                       _entry_Location.Text,
                                                                                                       -1,
                                                                                                       int.Parse(_entry_Radius.Text)));

            if (newSess != null)
            {
                App.CurrentSession.RegisteredCrawlSessions.Add(newSess);
                UpdateUI(App.CurrentSession.RegisteredCrawlSessions);
            }
        }


        void UpdateUI(IEnumerable<CrawlSession> sessions)
        {
            string cspText = "CrawlRequests:";
            foreach (var sess in sessions)
                cspText += Environment.NewLine + $"'{sess.SearchParams.KeyWords}'," + $"'{sess.SearchParams.LocationStr}'," +
                                                 $"{sess.SearchParams.CategoryID}," + $"{sess.SearchParams.Radius}";

            //Notification & GUI Update
            //_notiService.PublishNotification(timeStr + " Neuen Suchpara", e.Href, e.ID);
            Device.BeginInvokeOnMainThread(() =>
            {
                _Layi.Children.Add(new Label() { Text = cspText, TextColor = Color.Green });
            });
        }

        private static string GetTimeStamp() => "[" + DateTime.Now.TimeOfDay.ToString().Substring(0, 8) + "]";
    }
}
