using skydiveLogs_api.Domain;
using skydiveLogs_api.DomainBusiness.Interfaces;
using skydiveLogs_api.DomainService.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;

namespace skydiveLogs_api.DomainBusiness
{
    public class DropZoneService : IDropZoneService
    {
        #region Public Constructors

        public DropZoneService(IDropZoneRepository dropZoneRepository,
                               IFavoriteDropZoneRepository favoriteDropZoneRepository,
                               IIdentityService identityService,
                               ICacheService cacheService)
        {
            _dropZoneRepository = dropZoneRepository;
            _favoriteDropZoneRepository = favoriteDropZoneRepository;
            _identityService = identityService;
            _cacheService = cacheService;
        }

        #endregion Public Constructors

        #region Public Methods

        public void AddNewDz(DropZone newdropZone)
        {
            _dropZoneRepository.Add(newdropZone);
            _cacheService.Delete(CacheType.DropZone);
        }

        public bool AddToFavorite(int dzId)
        {
            var dzToAddToFavorite = GetDzById(dzId);

            var favoriteDz = new FavoriteDropZone
            {
                DropZone = dzToAddToFavorite,
                User = _identityService.ConnectedUser
            };

            var result = _favoriteDropZoneRepository.Add(favoriteDz);

            return result > 0;
        }

        public void DeleteDzById(int id)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<DropZone> GetAllDzs()
        {
            var results = Enumerable.Empty<DropZone>();

            var dropzones = GetAllRefDzs();
            var favorites = _favoriteDropZoneRepository.GetAll(_identityService.ConnectedUser);

            results = from dropZone in dropzones
                      join favorite in favorites on dropZone.Id equals favorite.DropZone.Id into tmp
                      from favoriteDz in tmp.DefaultIfEmpty()
                      select new DropZone
                      {
                          Id = dropZone.Id,
                          Address = dropZone.Address,
                          Email = dropZone.Email,
                          Latitude = dropZone.Latitude,
                          Longitude = dropZone.Longitude,
                          Name = dropZone.Name,
                          Type = dropZone.Type,
                          Website = dropZone.Website,
                          IsFavorite = !(favoriteDz == null)
                      };

            return results.ToList();
        }

        public DropZone GetDzById(int id)
        {
            var allDzs = GetAllRefDzs();
            return allDzs.Single(g => g.Id == id);
        }

        public bool RemoveToFavorite(int dzId)
        {
            var result = _favoriteDropZoneRepository.Delete(dzId, _identityService.ConnectedUser.Id);

            return result > 0;
        }

        public bool UpdateDz(int id, DropZone dropZone)
        {
            dropZone.Id = id;

            return _dropZoneRepository.Update(dropZone);
        }

        private IEnumerable<DropZone> GetAllRefDzs()
        {
            if (!_cacheService.Contains(CacheType.DropZone))
                _cacheService.Put(CacheType.DropZone,
                                  _dropZoneRepository.GetAll(),
                                  5 * 60 * 1000);

            return _cacheService.Get<IEnumerable<DropZone>>(CacheType.DropZone);
        }

        #endregion Public Methods

        #region Private Fields

        private readonly ICacheService _cacheService;
        private readonly IDropZoneRepository _dropZoneRepository;
        private readonly IFavoriteDropZoneRepository _favoriteDropZoneRepository;
        private readonly IIdentityService _identityService;

        #endregion Private Fields
    }
}