using System;
using AVFoundation;
using com.hdl.on;
using CoreLocation;
using Foundation;

using UIKit;


namespace Shared
{
    public class BaseApplicationDelegate : UIApplicationDelegate
    {
        public static Action<UIApplication, NSDictionary> FinishedLaunchingAction;
        public static Action<UIApplication> OnResignActivationAction;
        public static Action<UIApplication> DidEnterBackgroundAction;
        public static Action<UIApplication> WillEnterForegroundAction;
        public static Action<UIApplication> OnActivatedAction;
        public static Action<UIApplication> WillTerminateAction;
        public static Action<string> DeviceTokenAction;
        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
        {
            registerForRemoteNotification(application);
            //var musicInfo = new MusicInfo { };
            //Volume.Init();

            FinishedLaunchingAction?.Invoke(application, launchOptions);
            //GPS
            if (Shared.Application.IsGpsEnable)
            {
                if (MyCLLocationManager.Instance.IsLocationServicesEnabled)
                {
                    switch (Shared.Application.CurrentGpsUseMode)
                    {
                        case Application.GpsUseMode.Always:
                            MyCLLocationManager.Instance.RequestAlwaysAuthorization();
                            break;
                        case Application.GpsUseMode.WhenInUse:
                            MyCLLocationManager.Instance.RequestWhenInUseAuthorization();
                            break;
                    }
                    if (launchOptions != null && launchOptions.ObjectForKey(UIApplication.LaunchOptionsLocationKey) != null)
                    {
                       MyCLLocationManager.Instance.StartMonitoringSignificantLocationChanges();
                    }
                    else
                    {
                        MyCLLocationManager.Instance.StartUpdatingLocation();
                    }
                }
                else {
                    ///TODO 可以提示用户打开定位权限
                }
            }
            return true;
        }

        /// <summary>
        /// 注册远程消息推送
        /// </summary>
        /// <param name="application">Application.</param>
        void registerForRemoteNotification(UIApplication application)
        {
            if (8 <= int.Parse(UIDevice.CurrentDevice.SystemVersion.Split('.')[0]))
            {
                // 1.注册UserNotification,以获取推送通知的权限
                var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, null);
                application.RegisterUserNotificationSettings(settings);

                // 2.注册远程推送
                application.RegisterForRemoteNotifications();
            }
            else
            {
                application.RegisterForRemoteNotificationTypes(UIRemoteNotificationType.NewsstandContentAvailability | UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound);
            }
        }
        
        class MyCLLocationManager : CLLocationManager
        {
            #region 定位
            public static MyCLLocationManager Instance
            {
                get
                {
                    if (locationManager == null)
                    {
                        locationManager = new MyCLLocationManager();
                        //设置是否允许系统自动暂停定位
                        locationManager.PausesLocationUpdatesAutomatically = false;
                        locationManager.AllowsBackgroundLocationUpdates = false;
                        //设置定位精度
                        locationManager.DesiredAccuracy = CLLocation.AccuracyKilometer;
                        locationManager.init();
                    }
                    return locationManager;
                }
            }

            //判断定位操作是否被允许  
            static MyCLLocationManager locationManager;
            //最小的移动速度 m/s
            float minSpeed = 3;
            
            //最小的移动距离 m
            float minInteval = 100;
            /// <summary>
            /// 用户是否允许定位功能
            /// </summary>
            public bool IsLocationServicesEnabled => LocationServicesEnabled;
            void init()
            {
                if (LocationServicesEnabled)
                {
                    //设置定位更新的最小距离
                    locationManager.DistanceFilter = minInteval;

                    locationManager.LocationsUpdated += (sender, e) =>
                    {
                        var location = e.Locations[e.Locations.Length - 1];
                        adjustDistanceFilter(location);
                        Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude);
                        //System.Console.WriteLine($"位置信息变化 经度{location.Coordinate.Longitude}  纬度{location.Coordinate.Latitude}");
                        //uploadToServer(location);
                    };

                }
            }
            
            //*  规则: 如果速度小于minSpeed m/s 则把触发范围设定为100m
            //*  否则将触发范围设定为minSpeed*minInteval
            //*  此时若速度变化超过10% 则更新当前的触发范围(这里限制是因为不能不停的设置distanceFilter,
            //*  否则uploadLocation会不停被触发)

            void adjustDistanceFilter(CLLocation location)
            {
                //NSLog(@"adjust:%f",location.speed);
                if (location.Speed < minSpeed)
                {
                    if (Math.Abs(DistanceFilter - minInteval) > 0.1f)
                    {
                        DistanceFilter = minInteval;
                    }
                }
                else
                {
                    var lastSpeed = DistanceFilter / minInteval;
                    if ((Math.Abs(lastSpeed - location.Speed) / lastSpeed > 0.1f) || (lastSpeed < 0))
                    {
                        float newSpeed = (int)(location.Speed + 0.5f);
                        float newFilter = newSpeed * minInteval;

                        DistanceFilter = newFilter;
                    }
                }
            }
            nint taskIdentifier = UIApplication.BackgroundTaskInvalid;
            void beingBackgroundUpdateTask()
            {
                taskIdentifier = UIApplication.SharedApplication.BeginBackgroundTask(() =>
                {
                    endBackgroundUpdateTask();
                });
            }

            void endBackgroundUpdateTask()
            {
                if (taskIdentifier != UIApplication.BackgroundTaskInvalid)
                {
                    UIApplication.SharedApplication.EndBackgroundTask(taskIdentifier);
                    taskIdentifier = UIApplication.BackgroundTaskInvalid;
                }
            }

//            void uploadToServer(CLLocation location)
//            {
//#warning 如果有较长时间的操作 比如HTTP上传 请使用beginBackgroundTaskWithExpirationHandler
//                if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Active)
//                {
//                    //HTTP upload
//                    Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude);
//                    endBackgroundUpdateTask();
//                }
//                else//后台定位
//                {
//                    //假如上一次的上传操作尚未结束 则直接return
//                    if (taskIdentifier != UIApplication.BackgroundTaskInvalid)
//                    {
//                        return;
//                    }
//                    beingBackgroundUpdateTask();
//                    //HTTP upload
//                    Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude);
//                    //上传完成记得调用
//                    endBackgroundUpdateTask();
//                }
//            }
            #endregion
        }

        public override void OnResignActivation(UIApplication application) => OnResignActivationAction?.Invoke(application);// Invoked when the application is about to move from active to inactive state.// This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) // or when the user quits the application and it begins the transition to the background state.// Games should use this method to pause the game.

        public override void DidEnterBackground(UIApplication application) => DidEnterBackgroundAction?.Invoke(application);// Use this method to release shared resources, save user data, invalidate timers and store the application state.// If your application supports background exection this method is called instead of WillTerminate when the user quits.

        public override void WillEnterForeground(UIApplication application) => WillEnterForegroundAction?.Invoke(application);// Called as part of the transiton from background to active state.// Here you can undo many of the changes made on entering the background.

        public override void OnActivated(UIApplication application)
        {
            AVAudioSession.SharedInstance().SetActive(true);
            OnActivatedAction?.Invoke(application);
            // Restart any tasks that were paused (or not yet started) while the application was inactive. 
            // If the application was previously in the background, optionally refresh the user interface.
        }

        public override void WillTerminate(UIApplication application) => WillTerminateAction?.Invoke(application);// Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
        /// <summary>
        /// 注册远程消息推送回调方法
        /// </summary>
        /// <param name="application">Application.</param>
        /// <param name="deviceToken">Device token.</param>
        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            var bytes = new byte[deviceToken.Length];
            System.Runtime.InteropServices.Marshal.Copy(deviceToken.Bytes, bytes, 0, bytes.Length);

            var stringBuilder = new System.Text.StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                stringBuilder.AppendFormat("{0:x2}", bytes[i]);
            }
            var newDeviceToken = stringBuilder.ToString();
   
            var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");

            if (oldDeviceToken != newDeviceToken)
            {
                // Save new device token
                NSUserDefaults.StandardUserDefaults.SetString(newDeviceToken, "PushDeviceToken");
            }
            DeviceTokenAction?.Invoke(newDeviceToken);
        }

        public virtual void setHDLRootViewController() {


        }

    }
}