using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using Android.Content.PM;
using GMCabsDriverAssistant;
using GMCabsDriverAssistant.Messages;
using GMCabsDriverAssistant.Models;
using GMCabsDriverAssistant.Services;
using GMCabsDriverAssistant.Utils;
using GMCabsDriverAssistantSolution.Models.Rydo;
using GMCabsDriverAssistantSolution.Views;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Sentry;

namespace GMCabsDriverAssistantSolution.ViewModels
{
    public class HomeViewModel : BaseViewModel
    {
        #region Constants

        private const int LOCATION_CHECK_TIME_INTERVAL = 10;
        private const int LOCATION_READ_TIMEOUT = 10;
        private const double LOCATION_DISTANCE = 0.01;

        private double lastLatitude = 0.00, lastLongitude = 0.00;

        #endregion Constants

        #region Fields
        public int seconds = 180;
        public string timerSeconds = "3:00";
        public string pickUpAddress = "";
        public string dropUpAddress = "";
        private bool isVisibleAcceptBookingView = false;
        private readonly LoginResponseDto loginResponseDto = new LoginResponseDto();
        private bool hasUnreadNotifications;
        private bool isBookingAvailable;
        private CancellationTokenSource cts;
        private List<Guid> receivedBookingIDs;
        public List<Guid> availableBookingIDs = new List<Guid>();
        public bool isLocationPermitted;
        #endregion

        #region Properties 
        public bool IsVisibleAcceptBookingView
        {
            get => isVisibleAcceptBookingView;
            set
            {
                SetProperty(ref isVisibleAcceptBookingView, value);
                CustomTimer();
            }
        }
        public string PickUpAddress
        {
            get => pickUpAddress;
            set
            {
                SetProperty(ref pickUpAddress, value);
            }
        }
        public string DropUpAddress
        {
            get => dropUpAddress;
            set
            {
                SetProperty(ref dropUpAddress, value);
            }
        }
        public bool HasUnreadNotifications
        {
            get => hasUnreadNotifications;
            set => SetProperty(ref hasUnreadNotifications, value);
        }
        public bool IsBookingAvailable
        {
            get => isBookingAvailable;
            set => SetProperty(ref isBookingAvailable, value);
        }
        public string TimerSeconds
        {
            get => timerSeconds;
            set => SetProperty(ref timerSeconds, value);
        }
        public Location CurrentLocation { get; set; }
        readonly ILocationConsent locationConsent;
        #endregion

        #region Constructor

        public HomeViewModel()
        {
            Title = "Home";
            GetToken();
            locationConsent = DependencyService.Get<ILocationConsent>();
            //HandleReceivedMessages();
            //locationConsent.GetLocationConsent();

        }
        #endregion

        #region Methods 
        [Obsolete]
        public async Task OnAppearing()
        {
            isLocationPermitted = Preferences.Get(SecureStorageData.IsLocationPermitted, false);
            //SendForegroundAlarmManager();
            if (Device.RuntimePlatform != Device.iOS)
            {
                if (isLocationPermitted)
                {
                    if (!DependencyService.Resolve<IForegroundService>().IsForeGroundServiceRunning())
                    {
                        Preferences.Set("isForeground", "YES");
                        DependencyService.Resolve<IForegroundService>().StartMyForegroundService();
                    }
                }
            }
            else
            {
                var message = new StartServiceMessage();
                MessagingCenter.Send(message, "ServiceStarted");
            }
            UpdateDriverAppSelectedPermissions();
            GetUnreadNotificationCount();
            await GetCurrentLocation();
            await GetBookingAvailable();
            CheckBookingAndNotificationAvailibility();
        }

        public async void GetToken()
        {
            var token = Preferences.Get(SecureStorageData.Token, "");
            loginResponseDto.Token = Guid.Parse(token);
        }

        [Obsolete]
        public async void GetUnreadNotificationCount()
        {
            var token = Preferences.Get(SecureStorageData.Token, "");
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            var unreadNotification = await gmCabsDriverService.GetUnreadNotificationCount(token);
            if (unreadNotification != null)
            {
                if (unreadNotification.StatusCode == Constant.UNAUTHORIZED_CODE)
                {
                    GoToLoginPage();
                }
                else
                {
                    if (unreadNotification.UnreadNotificationCount > 0)
                    {
                        HasUnreadNotifications = true;
                    }
                    else
                    {
                        HasUnreadNotifications = false;
                    }
                }

            }

        }

        [Obsolete]
        private void GoToLoginPage()
        {
            Device.BeginInvokeOnMainThread(async () =>
            {

                if (Device.RuntimePlatform != Device.iOS)
                {
                    Preferences.Set("isForeground", "NO");
                    DependencyService.Resolve<IForegroundService>().StopMyForegroundService();
                }
                else if (Device.RuntimePlatform == Device.iOS)
                {
                    var message = new StopServiceMessage();
                    MessagingCenter.Send(message, "ServiceStopped");
                }
                var token = Preferences.Get(SecureStorageData.Token, "");
                Debug.WriteLine("TOKEN-------------", token);
                var lastLatitude = Convert.ToDouble(Preferences.Get("lastLat", "0"));
                var lastLongitude = Convert.ToDouble(Preferences.Get("lastLng", "0"));
                GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
                await gmCabsDriverService.LogoutDriverApp(token, lastLatitude, lastLongitude);
                SecureStorage.RemoveAll();
                Preferences.Clear();
                SentrySdk.ConfigureScope(scope =>
                {
                    scope.User = null;
                });
                await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
            });
        }


        private async Task GetBookingAvailable()
        {
            var canAcceptBookings = Preferences.Get(SecureStorageData.CanAcceptBookings, false);

            if (!canAcceptBookings || CurrentLocation == null)
            {
                return;
            }

            var accessToken = Preferences.Get(EftposLoginResponse.RYDO_ACCESS_TOKEN, "");
            var driverId = Preferences.Get(LoginResponseDto.USER_CODE, "");
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();

            availableBookingIDs = await gmCabsDriverService.GetBookingAvailableCount(accessToken, driverId, CurrentLocation.Latitude, CurrentLocation.Longitude);
            var cachedeBookingIds = await App.Database.GetBookingIdsAsync();

            if (availableBookingIDs != null && availableBookingIDs.Count > 0)
            {
                bool areNewBookings = false;
                //IEnumerable<Guid> newBookings = null;
                List<Guid> cachedBookings = new List<Guid>();

                if (cachedeBookingIds.Count == 0)
                {
                    await App.Database.SaveBookingIdsAsync(availableBookingIDs.Select(g => g.ToString()));
                    areNewBookings = true;
                }
                else
                {
                    foreach (var availableBooking in cachedeBookingIds)
                    {
                        cachedBookings.Add(Guid.Parse(availableBooking.BookingID));
                    }
                    int cachedBookingsCount = cachedBookings.Count();
                    var newBookings = availableBookingIDs.Except(cachedBookings);
                    if (newBookings.Count() > 0)
                    {
                        Console.WriteLine($"New Bookings Count: {newBookings.Count()}");
                        await App.Database.SaveBookingIdsAsync(newBookings.Select(g => g.ToString()));
                        areNewBookings = true;
                    }
                }

                IsBookingAvailable = true;
                //if (Device.RuntimePlatform == Device.iOS)
                //{
                //    if (areNewBookings)
                //    {
                //        var player = CrossSimpleAudioPlayer.Current;
                //        player.Load("newbooking.wav");
                //        player.Play();
                //    }
                //}
            }
            else
            {
                IsBookingAvailable = false;
                if (cachedeBookingIds.Count != 0)
                {
                    foreach (var availableBooking in cachedeBookingIds)
                    {
                        await App.Database.DeleteBookingIdsAsync(availableBooking);
                    }

                }
            }
        }

        async Task GetCurrentLocation()
        {
            try
            {
                if (isLocationPermitted)
                {
                    CurrentLocation = await Geolocation.GetLastKnownLocationAsync();

                    if (CurrentLocation == null)
                    {
                        var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(LOCATION_READ_TIMEOUT));
                        cts = new CancellationTokenSource();
                        //   CurrentLocation = await Geolocation.GetLocationAsync(request, cts.Token);
                        CurrentLocation = await Geolocation.GetLocationAsync(new GeolocationRequest
                        {
                            Timeout = TimeSpan.FromSeconds(50),
                            DesiredAccuracy = GeolocationAccuracy.Medium
                        });

                    }
                }
            }
            catch (FeatureNotSupportedException fnsEx)
            {
                // Handle not supported on device exception               
            }
            catch (FeatureNotEnabledException fneEx)
            {
                // Handle not enabled on device exception
            }
            catch (PermissionException pEx)
            {
                // Handle permission exception
            }
            catch (Exception ex)
            {
                // Unable to get location
            }
        }

        public void OnDisappearing()
        {
            if (cts != null && !cts.IsCancellationRequested)
                cts.Cancel();
        }

        [Obsolete]
        private void CustomTimer()
        {
            Device.StartTimer(TimeSpan.FromSeconds(1), () =>
            {
                if (!isVisibleAcceptBookingView)
                {
                    return false;
                }
                if (seconds > 0)
                {
                    --seconds;
                    TimerSeconds = seconds / 60 + ":" + (seconds % 60 <= 9 ? "0" + seconds % 60 : "" + seconds % 60);
                    return true;
                }
                else
                {
                    IsVisibleAcceptBookingView = false;
                    return false;
                }

            });
        }

        void HandleReceivedMessages()
        {
            //MessagingCenter.Subscribe<LocationMessage>(this, "Location", message =>
            //{
            //    Device.BeginInvokeOnMainThread(async () =>
            //    {
            //        Console.WriteLine(message.Latitude);
            //        Console.WriteLine(message.Longitude);

            //        var token = Preferences.Get(SecureStorageData.Token,"");
            //        if (token != null)
            //        {
            //            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            //            LocationUpdateRequestDto locationUpdateRequestDto = new LocationUpdateRequestDto();
            //            if (lastLatitude == 0.00 && lastLongitude == 0.00)
            //            {
            //                lastLatitude = message.Latitude;
            //                lastLongitude = message.Longitude;
            //                locationUpdateRequestDto.Latitude = message.Latitude;
            //                locationUpdateRequestDto.Longitude = message.Longitude;
            //                await gmCabsDriverService.SendDriverLocation(token, locationUpdateRequestDto);
            //            }
            //            else
            //            {
            //                Location lastLocation = new Location(lastLatitude, lastLongitude);
            //                Location currentLocation = new Location(message.Latitude, message.Longitude);                            
            //                double kilometers = Location.CalculateDistance(lastLocation, currentLocation, DistanceUnits.Kilometers);
            //                if (kilometers > LOCATION_DISTANCE)
            //                {
            //                    lastLatitude = message.Latitude;
            //                    lastLongitude = message.Longitude;
            //                    locationUpdateRequestDto.Latitude = message.Latitude;
            //                    locationUpdateRequestDto.Longitude = message.Longitude;
            //                    await gmCabsDriverService.SendDriverLocation(token, locationUpdateRequestDto);
            //                }
            //            }
            //            Preferences.Set("lastLat", message.Latitude);
            //            Preferences.Set("lastLng", message.Longitude);
            //        }
            //    });
            //});
            MessagingCenter.Subscribe<StopServiceMessage>(this, "ServiceStopped", message =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    // UserMessage = "Location Service has been stopped!";
                    Console.WriteLine("Location Service has been stopped!");
                });
            });
            MessagingCenter.Subscribe<LocationErrorMessage>(this, "LocationError", message =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    // UserMessage = "There was an error updating location!";
                    Console.WriteLine("There was an error updating location!");
                });
            });
        }
        private async Task GetBookingsWithOutNotificationSound()
        {
            var accessToken = Preferences.Get(EftposLoginResponse.RYDO_ACCESS_TOKEN, "");
            var driverId = Preferences.Get(LoginResponseDto.USER_CODE, "");
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            availableBookingIDs = await gmCabsDriverService.GetBookingAvailableCount(accessToken, driverId, CurrentLocation.Latitude, CurrentLocation.Longitude);
            if (availableBookingIDs.Count == 0)
            {
                IsBookingAvailable = false;
            }
        }

        [Obsolete]
        private void CheckBookingAndNotificationAvailibility()
        {
            Device.StartTimer(TimeSpan.FromSeconds(LOCATION_CHECK_TIME_INTERVAL), () =>
            {
                var isForeground = ShareConstant.IsInForeground;
                Task.Run(async () =>
                {
                    //GetUnreadNotificationCount(); //For avoiding duplicate call of UnreadCount API
                    await GetBookingsWithOutNotificationSound();
                });
                return isForeground;
            });
        }

        [Obsolete]
        private void SendForegroundAlarmManager()
        {
            Device.StartTimer(TimeSpan.FromMinutes(Constant.TIMER_MINUTES), () =>
            {
                var serviceRunningStatus = DependencyService.Resolve<IForegroundService>().IsForeGroundServiceRunning();
                if (serviceRunningStatus)
                {
                    DependencyService.Resolve<IAlarmService>().StartMyAlarmService();
                }
                return serviceRunningStatus;
            });
        }

        [Obsolete]
        public async Task UpdateLocation()
        {
            await GetCurrentLocation();
            if (CurrentLocation != null)
            {
                var response = await UpdateLocationOnServer(CurrentLocation.Latitude, CurrentLocation.Longitude);
                if (response == Constant.SUCCESS_CODE)
                {
                    await GetBookingAvailable();
                }
                else if (response == Constant.UNAUTHORIZED_CODE)
                {
                    GoToLoginPage();
                }
            }
        }

        private async Task<int> UpdateLocationOnServer(double currentLatitude, double currentLongitude)
        {
            var token = Preferences.Get(SecureStorageData.Token, "");
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            LocationUpdateRequestDto locationUpdateRequestDto = new LocationUpdateRequestDto();
            locationUpdateRequestDto.Latitude = currentLatitude;
            locationUpdateRequestDto.Longitude = currentLongitude;
            var responce = await gmCabsDriverService.SendDriverLocation(token, locationUpdateRequestDto);
            Preferences.Set("lastLat", currentLatitude);
            Preferences.Set("lastLng", currentLongitude);
            return responce;
        }

        private async void UpdateDriverAppSelectedPermissions()
        {
            var token = Preferences.Get(SecureStorageData.Token, "");
            var isLocationPermitted = Preferences.Get(SecureStorageData.IsLocationPermitted, false);
            var isBatteryOptimizationDisabled = Preferences.Get(SecureStorageData.IsBatteryOptimizationDisabled, false);
            var driverAppSelectedPermissionsDto = new DriverAppSelectedPermissionsDto();
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            driverAppSelectedPermissionsDto.LocationSetToAlways = isLocationPermitted;
            driverAppSelectedPermissionsDto.BatteryOptimisationDisabled = isBatteryOptimizationDisabled;
            await gmCabsDriverService.DriverAppSelectedPermissions(token, driverAppSelectedPermissionsDto);
        }
        #endregion
    }

}
