using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace Shride.Models
{
    public class RideRepository : IRideRepository
    {
        private RideDbContext context;
        private IHttpContextAccessor contextAccessor;

        public RideRepository(RideDbContext ctx, IHttpContextAccessor acc)
        {
            context = ctx;
            contextAccessor = acc;
        }

        public IQueryable<Account> Accounts => context.Accounts.Include(a => a.Persons).Include(a => a.Events).Include(a => a.Vehicles);
        public IQueryable<Event> Events => context.Events.Include(e => e.Rides);
        public IQueryable<Person> Persons => context.Persons.Include(p => p.Rides);
        public IQueryable<Review> Reviews => context.Reviews;
        public IQueryable<Ride> Rides => context.Rides.Include(r => r.Persons).Include(r => r.Transactions).Include(r => r.Reviews);
        public IQueryable<Transaction> Transactions => context.Transactions;
        public IQueryable<Vehicle> Vehicles => context.Vehicles.Include(v => v.Rides);

        public Account UserAccount => Accounts.Where(account => account.Name == contextAccessor.HttpContext.User.Identity.Name).First();

        public void AddVehicle(Vehicle vehicle)
        {
            if (vehicle != null)
            {
                UserAccount.Vehicles.Add(vehicle);
            }
            context.SaveChanges();
        }

        public IQueryable<Ride> FoundRides(double startLat, double endLat, double startLng, double endLng, DateTime departure, int seats)
        {
            //Ride ride = new Ride();
            //ride.StartLat;
            //ride.StartLng;
            //-ride.EndLat;
            //-ride.EndLng;
            //ride.Departure;
            //ride.Cancelled;
            //ride.Seats;
            IQueryable<Ride> foundRides = Rides.Where(ride => ride.EndLat.Equals(endLat)).
                Where(ride => ride.EndLng.Equals(endLng));
            return foundRides;
        }

        //public IQueryable<Review> RideReview => Reviews.Where(review => review.RideId.Equals());
        public void AddPerson(Person person)
        {
            if (person != null)
            {
                UserAccount.Persons.Add(person);
            }
            context.SaveChanges();
        }

        public void AddAccount(Account account)
        {
            if (account != null)
            {
                if (!context.Accounts.Any(a => a.Name == account.Name))
                {
                    context.Accounts.AddAsync(account);
                }
                context.SaveChanges();
            }
        }

        public void AddEvent(Event e)
        {
            if (e != null)
            {
                context.Events.Add(e);
            }
            context.SaveChanges();
        }

        public IQueryable<Event> SearchEvent()
        {

            return context.Events; //Ändra till sökning
        }

        public void BookRide(Booking bookRide)
        {
            if (bookRide != null)
            {
                if (bookRide.Person.Rides == null)
                {
                    bookRide.Person.Rides = new Collection<Ride>();

                }
                if (bookRide.Ride.Persons == null)
                {
                    bookRide.Ride.Persons = new Collection<Person>();

                }
                bookRide.Person.Rides.Add(bookRide.Ride);
                bookRide.Ride.Persons.Add(bookRide.Person);

                int seats = bookRide.Ride.Seats;
                bookRide.Ride.Seats = seats - 1;
            }
            context.SaveChanges();
        }

        public IQueryable<Ride> SearchRide()
        {

            return context.Rides; //Ändra till sökning
        }

        public Ride GetRide(int id)
        {
            return context.Rides.Where(ride => ride.RideId == id).First();
        }

        public void CancelRide(Ride ride, Person person)
        {
            if (ride != null)
            {
                person.Rides.Remove(ride);
                ride.Persons.Remove(person);
            }
            context.SaveChanges();
        }

        public void AddRide(Ride ride, int vehicleId)
        {
            if (ride != null)
            {
                Vehicle vehicle = Vehicles.Where(v => v.VehicleId == vehicleId).First();
                vehicle.Rides.Add(ride);
            }
            context.SaveChanges();
        }

        public void Pay(Transaction transaction)
        {
            if (transaction != null)
            {
                context.Transactions.Add(transaction);
            }
            context.SaveChanges();
        }

        public void Review(Review review)
        {
            if (review != null)
            {
                context.Reviews.Add(review);
            }
            context.SaveChanges();
        }

        public LocationBundle GetCoordinatesAndLocation(string searchQuery)
        {
            searchQuery = searchQuery.Replace(',', '.');
            var coordinates = new LocationBundle();

            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");
            string json = (webClient).DownloadString("https://nominatim.openstreetmap.org/search.php?q=" + searchQuery + "&format=jsonv2");
            dynamic location = JsonConvert.DeserializeObject(json);

            if (!location.ToString().Equals("[]"))
            {
                coordinates.locationName = location[0].display_name; // name
                coordinates.lat = location[0].lat; //lat
                coordinates.lng = location[0].lon; //lng
                return coordinates;
            }
            else
            {
                return null;
            }
        }
    }
}
