using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Shride.Infrastructure;
using Shride.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;

namespace Shride.Controllers
{
    [Authorize]
    public class UserController : Controller
    {
        private IRideRepository repository;
        private IUserRepository uRepository;

        public UserController(IRideRepository repo, IUserRepository uRepo)
        {
            repository = repo;
            uRepository = uRepo;
        }

        public IActionResult AccountSettings()
        {
            return View();
        }

        public ViewResult Persons()
        {
            List<Person> persons = repository.UserAccount.Persons;
            return View(persons);
        }

        public IActionResult AddNewVehicle(Vehicle vehicle)
        {
            return View(vehicle);
        }

        public ViewResult Vehicles()
        {
            List<Vehicle> vehicles = repository.UserAccount.Vehicles;
            return View(vehicles);
        }

        public ViewResult VehicleAssigned(Vehicle vehicle)
        {
            repository.AddVehicle(vehicle);
            return View(vehicle);
        }

        public IActionResult CreateRide(string userSearchQuery, string confirmStart, string confirmEnd, string startLat, string startLon, string endLat, string endLon, int seats, int vehicleId, int personId, DateTime departure, bool confirm)
        {
            // variabler för att spara tidigare sökningar
            if (confirm == true)
            {
                var newRide = new Ride();
                newRide.StartLat = Double.Parse(startLat.Replace('.', ','));
                newRide.StartLng = Double.Parse(startLon.Replace('.', ','));
                newRide.EndLat = Double.Parse(endLat.Replace('.', ','));
                newRide.EndLng = Double.Parse(endLon.Replace('.', ','));
                newRide.Departure = departure;
                newRide.Seats = seats;

                HttpContext.Session.SetJson("r", newRide);
                HttpContext.Session.SetJson("p", personId);
                HttpContext.Session.SetJson("v", vehicleId);

                return RedirectToAction("CreatedRide", "User");
            }
            ViewBag.ListOfVehicles = repository.UserAccount.Vehicles;
            ViewBag.ListOfPersons = repository.UserAccount.Persons;
            if (ViewBag.startLat == null && ViewBag.startLon == null)
            {
                ViewBag.startLat = startLat;
                ViewBag.startLon = startLon;
            }
            if (ViewBag.endLat == null && ViewBag.endLon == null)
            {
                ViewBag.endLat = endLat;
                ViewBag.endLon = endLon;
            }
            if (ViewBag.confirmStart == null)
            {
                ViewBag.confirmStart = confirmStart;
            }
            if (ViewBag.confirmEnd == null)
            {
                ViewBag.confirmEnd = confirmEnd;
            }
            if (ViewBag.seats == null)
            {
                seats = ViewBag.ListOfVehicles[0].Seats;
                ViewBag.seats = seats;
            }
            if (ViewBag.departure == null)
            {
                ViewBag.departure = departure;
            }
            // Startpositionen som visas om användaren inte har sökt efter något
            if (userSearchQuery == null)
            {
                ViewBag.userSearchQuery = "visby gotland";
            }
            else
            {
                ViewBag.userSearchQuery = userSearchQuery;
            }

            // skapa korrekta värden för att API ska tillåta koppling
            WebClient webClient = new WebClient();
            webClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
            webClient.Headers.Add("Referer", "http://www.microsoft.com");

            // skapa koppling till API med användarens sökquery och göra om till String
            string json = (webClient).DownloadString("https://nominatim.openstreetmap.org/search.php?q=" + ViewBag.userSearchQuery + "&format=jsonv2");

            // Gör dynamisk objekt av json-String för att kunna anropa innehållet
            dynamic location = JsonConvert.DeserializeObject(json);

            // Koordinaterna i location ändrar den embeddade kartan dynamiskt genom att lägga in variabler där koordinater ska läsas in
            // Hoppar till else-sats om API inte kan hitta platsen, då visar den i stället default visby gotland
            if (!location.ToString().Equals("[]"))
            {
                ViewBag.locationName = location[0].display_name;

                ViewBag.bboxOne = location[0].boundingbox[2]; // 2
                ViewBag.bboxTwo = location[0].boundingbox[0]; // 0
                ViewBag.bboxThree = location[0].boundingbox[3]; // 3
                ViewBag.bboxFour = location[0].boundingbox[1]; // 1
                ViewBag.lat = location[0].lat; // lat
                ViewBag.lon = location[0].lon; // long
                // Länken som används embeddad i View för att visa kartan
                ViewBag.link = "https://www.openstreetmap.org/export/embed.html?bbox=" + ViewBag.bboxOne + "%2C" + ViewBag.bboxTwo + "%2C" + ViewBag.bboxThree + "%2C" + ViewBag.bboxFour + "&amp;layer=mapnik&amp;marker=" + ViewBag.lat + "%2C" + ViewBag.lon + "";
            }
            else
            {
                ViewBag.locationName = "Kunde ej hitta plats, försök igen.";
                ViewBag.link = "https://www.openstreetmap.org/export/embed.html?bbox=17.976379394531254%2C57.46415790200031%2C18.58268737792969%2C57.811480309436845&amp;layer=mapnik&amp;marker=57.638234420786176%2C18.27953338623047";
            }

            /*Annat anrop för att få avstånd mellan start och slut*/
            if (ViewBag.confirmStart != null && ViewBag.confirmEnd != null && ViewBag.confirmStart != ViewBag.confirmEnd)
            {
                WebClient directionsWebClient = new WebClient();
                directionsWebClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                directionsWebClient.Headers.Add("Referer", "http://www.microsoft.com");
                string directionsJson = (directionsWebClient).DownloadString("https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597851110001cf6248904e7a8353f248b5a8e4e3ad9dc96340&start=" + ViewBag.startLon + "," + ViewBag.startLat + "&end=" + ViewBag.endLon + "," + ViewBag.endLat + "");
                dynamic directions = JsonConvert.DeserializeObject(directionsJson);

                ViewBag.distance = Math.Round((Double)(directions.features[0].properties.summary.distance / 1000), 1) + " km.";
            }
            return View();
        }

        public IActionResult CreatedRide(Ride ride)
        {
            ride = HttpContext.Session.GetJson<Ride>("r");
            int personId = HttpContext.Session.GetJson<int>("p");
            int vehicleId = HttpContext.Session.GetJson<int>("v");
            ViewBag.start = repository.GetCoordinatesAndLocation(ride.StartLat + " " + ride.StartLng).locationName;
            ride.Start = ViewBag.start;
            ViewBag.end = repository.GetCoordinatesAndLocation(ride.EndLat + " " + ride.EndLng).locationName;
            ride.End = ViewBag.end;
            repository.AddRide(ride, vehicleId);
            Booking bookRide = new Booking();
            bookRide.Person = repository.Persons.Where(person => person.PersonId == personId).First();
            bookRide.Ride = ride;
            repository.BookRide(bookRide);

            ViewBag.driver = bookRide.Person.FirstName + " " + bookRide.Person.LastName;
            ViewBag.vehicle = bookRide.Ride.Vehicle.RegNr;
            
            return View(ride);
        }
        public IActionResult CreateEvent(Event e, string userSearchQuery)
        {
            ViewBag.locationName = "Sök efter plats";
            if (ViewBag.userSearchQuery == null && userSearchQuery != null)
            {
                ViewBag.userSearchQuery = userSearchQuery;
                var locationBundle = repository.GetCoordinatesAndLocation(userSearchQuery);

                if (locationBundle != null)
                {
                    ViewBag.locationName = locationBundle.locationName;
                    e.LocationLat = locationBundle.lat;
                    e.LocationLng = locationBundle.lng;
                    HttpContext.Session.SetJson("ev", e);
                }
                else
                {
                    ViewBag.locationName = "Kunde ej hitta plats, försök igen.";
                }
            }
            return View(e);
        }

        public IActionResult CreatedEvent(Event e, string locationName)
        {
            e = HttpContext.Session.GetJson<Event>("ev");
            e.AccountId = repository.UserAccount.AccountId;
            repository.AddEvent(e);
            ViewBag.location = locationName;

            return View(e);
        }

        public IActionResult CreatePerson(Person person)
        {
            person.BirthDate = DateTime.Today;

            return View(person);
        }

        public ViewResult PersonAssigned(Person person)
        {
            if (person != null)
            {
                repository.AddPerson(person);
            }
            return View(person);
        }

        public async Task<IActionResult> DashboardAsync()  // Behöver göra klart inlogg innan login skickar vidare användaren till dashboard, så den får stanna i Home-mappen tillsvidare
        {
            var currentUser = await uRepository.GetUser(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
            User user = new User();
            user.UserName = currentUser.UserName;
            user.Email = currentUser.Email;
            user.Phone = currentUser.PhoneNumber;
            return View(user);
        }

        public IActionResult DeleteAccount()
        {
            return View();
        }
        public IActionResult UserSearchEvent()
        {
            IQueryable<Event> events = repository.SearchEvent();
            return View(events);
        }

        public IActionResult UserSearchRide(string start, string end)
        {
            if (start != null || end != null)
            {
                var locationBundleStart = repository.GetCoordinatesAndLocation(start);
                var locationBundleEnd = repository.GetCoordinatesAndLocation(end);
            }

            IQueryable<Ride> rides = repository.SearchRide();
            return View(rides);
        }

        public ViewResult BookRide(Booking booking, int id)
        {
            ViewBag.Id = id;
            ViewBag.ListOfPersons = repository.UserAccount.Persons;
            Ride ride = new Ride();
            //ride = repository.Rides.Where(r => r.RideId == id).First();
            HttpContext.Session.SetJson("id", id);
            return View(booking);
        }

        public ViewResult BookedRide(Booking booking, int personId)
        {
            int id = HttpContext.Session.GetJson<int>("id");
            booking.Ride = repository.Rides.Where(r => r.RideId == id).First(); 
            booking.Person = repository.UserAccount.Persons.Where(person => person.PersonId == personId).First();
            repository.BookRide(booking);
            return View(booking);
        }
    }
}
