using System;
using System.Net.Http;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using ModernHttpClient;
using Xamarin.SSO.Client;

namespace XamarinStore
{
	public class WebService
	{
		public static readonly WebService Shared = new WebService ();

		public User CurrentUser { get; set; }
		public Order CurrentOrder { get; set; }

	    readonly XamarinSSOClient _client = new XamarinSSOClient ("https://auth.xamarin.com", "0c833t3w37jq58dj249dt675a465k6b0rz090zl3jpoa9jw8vz7y6awpj5ox0qmb");

		public WebService ()
		{
			CurrentOrder = new Order ();
		}

		public async Task<bool> Login (string username, string password)
		{
		    try {
			    AccountResponse response;
			    var request = Task.Run (() => response = _client.CreateToken (username, password));
				response = await request;
				if (response.Success) {
					var user = response.User;
					CurrentUser = new  User {
						LastName = user.LastName,
						FirstName = user.FirstName,
						Email = username,
						Token = response.Token
					};
					return true;
				}
		        Console.WriteLine ("Login failed: {0}", response.Error);
		    } catch (Exception ex) {
				Console.WriteLine ("Login failed for some reason...: {0}", ex.Message);
			}
			return false;
		}

		List<Product> _products;
		public async Task<List<Product>> GetProducts()
		{
			if (_products == null) {
				try {
					string extraParams = "";

					//TODO: Get a Monkey!!!
					//extraParams = "?includeMonkeys=true";

					var httpClient = CreateClient();
                    var content = await httpClient.GetStringAsync("https://xamarin-store-app.xamarin.com/api/products" + extraParams);
                    _products = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Product>>(content);
				} catch (Exception ex) {
					Console.WriteLine (ex);
					_products = new List<Product> ();
				}

			}
			return _products;
		}

		bool _hasPreloadedImages;
		public async Task PreloadImages(float imageWidth)
		{
			if (_hasPreloadedImages)
				return;
			_hasPreloadedImages = true;
			//Lets precach the countries too
			await GetCountries ();
			await Task.Factory.StartNew (() => {
				var imagUrls = _products.SelectMany (x => x.ImageUrls.Select (y => Product.ImageForSize (y, imageWidth))).ToList ();
				imagUrls.ForEach( async (x) => await FileCache.Download(x));

			});


		}
		List<Country> _countries = new List<Country>();
		public async Task<List<Country>> GetCountries()
		{
			try {

				if(_countries.Count > 0)
					return _countries;

				var httpClient = CreateClient();
                var content = await httpClient.GetStringAsync("https://xamarin-store-app.xamarin.com/api/Countries");
				_countries = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Country>> (content);
				return _countries;
			} catch (Exception ex) {
				Console.WriteLine (ex);
				return new List<Country> ();
			}
		}

		public async Task<string> GetCountryCode(string country)
		{
			var c = (await GetCountries ()).FirstOrDefault (x => x.Name == country) ?? new Country();

			return c.Code;
		}

		public async Task<string> GetCountryFromCode(string code)
		{
			var c = (await GetCountries ()).FirstOrDefault (x => x.Code == code) ?? new Country();

			return c.Name;
		}

		//No need to await anything, and no need to spawn a task to return a list.
		#pragma warning disable 1998
		public async Task<List<string>> GetStates(string country)
		{
			if (country.ToLower () == "united states")
				return new List<string> {
					"Alabama",
					"Alaska", 
					"Arizona",
					"Arkansas",
					"California",
					"Colorado",
					"Connecticut",
					"Delaware",
					"District of Columbia",
					"Florida",
					"Georgia",
					"Hawaii",
					"Idaho",
					"Illinois",
					"Indiana",
					"Iowa",
					"Kansas",
					"Kentucky",
					"Louisiana",
					"Maine",
					"Maryland",
					"Massachusetts",
					"Michigan",
					"Minnesota",
					"Mississippi",
					"Missouri",
					"Montana",
					"Nebraska",
					"Nevada",
					"New Hampshire",
					"New Jersey",
					"New Mexico",
					"New York",
					"North Carolina",
					"North Dakota",
					"Ohio",
					"Oklahoma",
					"Oregon",
					"Pennsylvania",
					"Rhode Island",
					"South Carolina",
					"South Dakota",
					"Tennessee",
					"Texas",
					"Utah",
					"Vermont",
					"Virginia",
					"Washington",
					"West Virginia",
					"Wisconsin",
					"Wyoming",
				};
			return new List<string> ();
		}
		#pragma warning restore 1998

		static HttpClient CreateClient()
		{
#if __IOS__
            return new HttpClient(new NSUrlSessionHandler());
#else
            return new HttpClient(new OkHttpNetworkHandler());
#endif
		}
			

		public async Task<OrderResult> PlaceOrder (User user, bool verify = false) 
        {
			try {
                var httpClient = CreateClient();
				var res =
                    await httpClient.PostAsync("order" + (verify ? "?verify=1" : ""), new StringContent(CurrentOrder.GetJson(user)));

                res.EnsureSuccessStatusCode();

			    var json = await res.Content.ReadAsStringAsync();
                var result = Newtonsoft.Json.JsonConvert.DeserializeObject<OrderResult>(json);
				if(!verify && result.Success)
					CurrentOrder = new Order();
				return result;
			} catch (Exception ex) {
				return new OrderResult {
					Success = false,
					Message = ex.Message,
				};
			}
		}
	}
}

