#define SHOW_FAKE_POSITION_IN_SIMULATOR

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.CoreLocation;
using MonoTouch.MapKit;

namespace Pages
{
	public partial class GPSPage : UIViewController
	{
		#region Constructors

		// The IntPtr and initWithCoder constructors are required for items that need 
		// to be able to be created from a xib rather than from managed code

		public GPSPage(IntPtr handle) : base(handle)
		{
			Initialize();
		}

		[Export("initWithCoder:")]
		public GPSPage(NSCoder coder) : base(coder)
		{
			Initialize();
		}

		public GPSPage() : base("GPSPage", null)
		{
			Initialize();
		}

		void Initialize()
		{
		}

		#endregion

		CLLocationManager locationManager;

		private void UpdatedHeading(object sender, CLHeadingUpdatedEventArgs args)
		{
			if (args.NewHeading.HeadingAccuracy >= 0)
			{
				MagHeadingLabel.Text = string.Format("{0:F1}° ± {1:F1}°", args.NewHeading.MagneticHeading, args.NewHeading.HeadingAccuracy);
				TrueHeadingLabel.Text = string.Format("{0:F1}° ± {1:F1}°", args.NewHeading.TrueHeading, args.NewHeading.HeadingAccuracy);
			}
			else
			{
				MagHeadingLabel.Text = "N/A";
				TrueHeadingLabel.Text = "N/A";
			}
		}

		private void UpdatedLocation(object sender, CLLocationUpdatedEventArgs args)
		{
			const double LatitudeDelta = 0.002;
			//no. of degrees to show in the map
			const double LongitudeDelta = LatitudeDelta;
			
			var PosAccuracy = args.NewLocation.HorizontalAccuracy;
			if (PosAccuracy >= 0)
			{
				var Coord = args.NewLocation.Coordinate;
				//In simulator, MapKit's user location is fixed on Apple's HQ but
				//CoreLocation will happily detect current location via network
				//(contrary to Apple docs)
				#if SHOW_FAKE_POSITION_IN_SIMULATOR
				//Use MapKit's notion of the current user location
				if (DeviceHardware.InSimulator)
				{
					Coord = MapView.UserLocation.Coordinate;
					PosAccuracy = 100;
				}
				#endif				
				LatitudeLabel.Text = string.Format("{0:F6}° ± {1} m", Coord.Latitude, PosAccuracy);
				LongitudeLabel.Text = string.Format("{0:F6}° ± {1} m", Coord.Longitude, PosAccuracy);
				if (Coord.IsValid())
				{
					var region = new MKCoordinateRegion(Coord, new MKCoordinateSpan(LatitudeDelta, LongitudeDelta));
					MapView.SetRegion(region, false);
					MapView.SetCenterCoordinate(Coord, false);
					MapView.SelectAnnotation(MapView.UserLocation, false);
				}
			}
			else
			{
				LatitudeLabel.Text = "N/A";
				LongitudeLabel.Text = "N/A";
			}
			if (args.NewLocation.VerticalAccuracy >= 0)
				AltitudeLabel.Text = string.Format("{0:F6} m ± {1} m", args.NewLocation.Altitude, args.NewLocation.VerticalAccuracy);
			else
				AltitudeLabel.Text = "N/A";
			if (args.NewLocation.Course >= 0)
				CourseLabel.Text = string.Format("{0}°", args.NewLocation.Course);
			else
				CourseLabel.Text = "N/A";
			SpeedLabel.Text = string.Format("{0} m/s", args.NewLocation.Speed);
			
		}

		public override void ViewDidAppear(bool animated)
		{
			base.ViewDidAppear(animated);
			if ((InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft) || 
				(InterfaceOrientation == UIInterfaceOrientation.LandscapeRight))
				SetupUIForOrientation(InterfaceOrientation);
				
			MapView.WillStartLoadingMap += (s, e) => { UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true; };
			MapView.MapLoaded += (s, e) => { UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false; };
			MapView.LoadingMapFailed += (s, e) => { UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false; };
			MapView.MapType = MKMapType.Hybrid;
			MapView.ShowsUserLocation = true;
			//Set up the text attributes for the user location annotation callout
			MapView.UserLocation.Title = "You are here";
			MapView.UserLocation.Subtitle = "YA RLY!";
			
			locationManager = new CLLocationManager();
			locationManager.DesiredAccuracy = -1;
			//Be as accurate as possible
			locationManager.DistanceFilter = 50;
			//Update when we have moved 50 m
			locationManager.HeadingFilter = 1;
			//Update when heading changes 1 degree 
			locationManager.UpdatedHeading += UpdatedHeading;
			locationManager.UpdatedLocation += UpdatedLocation;
			locationManager.StartUpdatingLocation();
			locationManager.StartUpdatingHeading();
		}

		public override void ViewDidDisappear(bool animated)
		{
			locationManager.StopUpdatingHeading();
			locationManager.StopUpdatingLocation();
			locationManager.Dispose();
			locationManager = null;
			base.ViewDidDisappear(animated);
		}
		
		public override bool ShouldAutorotateToInterfaceOrientation(UIInterfaceOrientation toInterfaceOrientation)
		{
			return true;
		}
		
		private void SetupUIForOrientation(UIInterfaceOrientation orientation)
		{
			//iPhone is 320x480
			//iPad is 768x1024
			var DeviceHeight = (int)UIScreen.MainScreen.Bounds.Height;
			var DeviceWidth = (int)UIScreen.MainScreen.Bounds.Width;
			const int NavBarHghtPortrait = 44;
			const int NavBarHghtLandscape = 32;
			const int TextLabelsWidth = 270;
			const int TextLabelsHeight = 257;
			var AppFrame = UIScreen.MainScreen.ApplicationFrame;
			if ((orientation == UIInterfaceOrientation.Portrait) || (orientation == UIInterfaceOrientation.PortraitUpsideDown))
				MapView.Frame = RectangleF.FromLTRB(0, TextLabelsHeight, DeviceWidth, AppFrame.Height - NavBarHghtPortrait);
			else
				MapView.Frame = RectangleF.FromLTRB(TextLabelsWidth, 0, DeviceHeight, AppFrame.Width - NavBarHghtLandscape);
		}
		
		public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
		{
			base.WillAnimateRotation(toInterfaceOrientation, duration);
			SetupUIForOrientation(toInterfaceOrientation);
		}
	}
}
