using System;
using System.Collections.Generic;
using System.Windows.Media;

namespace ChatController.Core
{
    public class OwnChatCache
    {
        public long? LoggedOnUserId { get; set; }

        private static readonly object _Lock = new object();

        // Key-> "group-127" oder "user-938"
        private Dictionary<string, ImageSourceCacheStorage> _ImageSourceCache = new Dictionary<string, ImageSourceCacheStorage>();

        private readonly Dictionary<long, ProfilePictureObject> _UserProfilePictures = new Dictionary<long, ProfilePictureObject>();

        private static OwnChatCache _Instance;

        private OwnChatCache() { }

        public static OwnChatCache GetInstance()
        {
            return _Instance ?? (_Instance = new OwnChatCache());
        }

        public void ClearAll()
        {
            ClearImageSources();
        }

        public void ClearImageSources()
        {
            lock(_Lock)
            {
                _ImageSourceCache.Clear();
            }
        }

        public ImageSource GetImageSourceFromCache(string key, string name, CacheCategory cacheCategory)
        {
            lock(_Lock)
            {
                if(key == null || _ImageSourceCache == null || !_ImageSourceCache.ContainsKey(key))
                {
                    return null;
                }
            
                var imageSourceCacheObject = _ImageSourceCache[key].GetCachedImageSource(cacheCategory, name);

                return imageSourceCacheObject?.Image;
            }
        }

        public void AddImageToCache(string key, ImageSource imageSource, CacheCategory cacheCategory, string name)
        {
            lock(_Lock)
            {
                if(_ImageSourceCache == null)
                {
                    _ImageSourceCache = new Dictionary<string, ImageSourceCacheStorage>();
                }

                if(!_ImageSourceCache.ContainsKey(key))
                {
                    _ImageSourceCache.Add(key, new ImageSourceCacheStorage());
                }

                _ImageSourceCache[key].AddImageSourceToCachedObjects(imageSource, cacheCategory, name);
            }
        }

        public void AddProfilePictureToCache(string key, ImageSource imageSource, string profilePicturePath)
        {
            lock(_Lock)
            {
                if(!_ImageSourceCache.ContainsKey(key))
                {
                    _ImageSourceCache.Add(key, new ImageSourceCacheStorage());
                }
            
                _ImageSourceCache[key].SetCachedProfilePicture(imageSource, profilePicturePath);
            }
        }

        public ImageSource GetCachedProfilePicture(string key, string uri)
        {
            lock(_Lock)
            {
                foreach (var kvp in _ImageSourceCache)
                {
                    if(!string.IsNullOrWhiteSpace(uri) && uri.ToLower().Contains("ownchat") && kvp.Value.ProfilePicturePath == uri)
                    {
                        return kvp.Value.GetCachedProfilePicture();
                    }
                }
                
                return _ImageSourceCache.ContainsKey(key) ? 
                       _ImageSourceCache[key].GetCachedProfilePicture() : 
                       null;
            }
        }

        public void AddUserProfilePictureToCache(ImageSource imageSource, long userId, string uri)
        {
            lock(_Lock)
            {
                if(!_UserProfilePictures.ContainsKey(userId))
                {
                    _UserProfilePictures.Add(userId, new ProfilePictureObject(userId, uri, imageSource));
                }
            }
        }

        public ProfilePictureObject GetUserProfilePictureFromCache(long userId)
        {
            lock(_Lock)
            {
                return _UserProfilePictures.ContainsKey(userId) ? _UserProfilePictures[userId] : null;
            }
        }

        public bool IsUserProfilePictureInCache(long userId)
        {
            lock(_Lock)
            {
                return _UserProfilePictures.ContainsKey(userId);
            }
        }
    }

    public class ProfilePictureObject
    {
        public long UserId { get; set; }

        public string Uri { get; set; }

        public ImageSource ProfilePicture { get; set; }

        public ProfilePictureObject(long userId, string uri, ImageSource profilePicture)
        {
            UserId = userId;
            Uri = uri;
            ProfilePicture = profilePicture;
        }
    }

    public class ImageSourceCacheStorage
    {
        private ImageSourceCacheObject _ProfilePicture;

        public string ProfilePicturePath { get; set; }

        public ImageSource GetCachedProfilePicture()
        {
            return _ProfilePicture?.ExpirationDate > DateTime.Now ? _ProfilePicture.Image : null;
        }

        public void SetCachedProfilePicture(ImageSource avatarImageSource, string profilePicturePath)
        {
            if(avatarImageSource != null && !string.IsNullOrWhiteSpace(profilePicturePath))
            {
                ProfilePicturePath = profilePicturePath;
                _ProfilePicture = new ImageSourceCacheObject(avatarImageSource, CacheCategory.ProfilePicture);
            }
        }

        public Dictionary<CacheCategory, Dictionary<string, ImageSourceCacheObject>> CachedObjects { get; set; }

        public ImageSourceCacheStorage()
        {
            CachedObjects = new Dictionary<CacheCategory, Dictionary<string, ImageSourceCacheObject>>();
        }

        public ImageSourceCacheObject GetCachedImageSource(CacheCategory cacheCategory, string name)
        {
            if(CachedObjects.ContainsKey(cacheCategory) && CachedObjects[cacheCategory].ContainsKey(name))
            {
                var imageSourceCacheObject = CachedObjects[cacheCategory][name];

                return imageSourceCacheObject?.ExpirationDate > DateTime.Now ? imageSourceCacheObject : null;
            }

            return null;
        }

        public void AddImageSourceToCachedObjects(ImageSource imageSource, CacheCategory cacheCategory, string name)
        {
            if(CachedObjects == null)
            {
                CachedObjects = new Dictionary<CacheCategory, Dictionary<string, ImageSourceCacheObject>>();
            }

            var newImageSourceCacheObject = new ImageSourceCacheObject(imageSource, cacheCategory);

            if(CachedObjects.ContainsKey(cacheCategory) )
            {
                if (CachedObjects[cacheCategory].ContainsKey(name))
                {
                    CachedObjects[cacheCategory][name] = newImageSourceCacheObject;
                }
                else
                {
                    CachedObjects[cacheCategory].Add(name, newImageSourceCacheObject);
                }
            }
            else
            {
                CachedObjects.Add(cacheCategory, new Dictionary<string, ImageSourceCacheObject> {{name, newImageSourceCacheObject } });
            }
        }
    }

    public class ImageSourceCacheObject
    {
        public CacheCategory CacheCategory { get; }

        public DateTime ExpirationDate { get; }

        public ImageSource Image { get; }

        public ImageSourceCacheObject(ImageSource imageSource, CacheCategory cacheCategory)
        {
            ExpirationDate = DateTime.Now.AddYears(1);
            Image          = imageSource;
            CacheCategory  = cacheCategory;
        }
    }

    public enum CacheCategory
    {
        ProfilePicture,
        Thumbnail,
        MessageAttachment
    }
}
