using PhotoFilter.Common;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;

namespace PhotoFilter
{
	public enum ImageLocation
	{
		CameraRoll,
		App,
		Unknown
	}
	public class ImageDescriptor
	{
		public ImageDescriptor(ImageLocation location, string fileName)
		{
			Location = location;
			FileName = fileName;
		}
		public ImageLocation Location { get; set; }
		public string FileName { get; set; }
	}

	public class ImageDescriptorComparer : IEqualityComparer<ImageDescriptor>
	{
		public bool Equals(ImageDescriptor x, ImageDescriptor y)
		{
			return (x.FileName == y.FileName && x.Location == y.Location);
		}

		public int GetHashCode(ImageDescriptor obj)
		{
			return (obj.FileName + obj.Location).GetHashCode();
		}
	}

	public class ImageCache
	{
		readonly Dictionary<ImageDescriptor, ImageItem> _imagesByDescriptor;

		public ImageCache()
		{
			ImageDescriptorComparer comparer = new ImageDescriptorComparer();
			_imagesByDescriptor = new Dictionary<ImageDescriptor, ImageItem>(comparer);
		}

		public bool TryGetImage(ImageDescriptor descriptor, out ImageItem image)
		{
			return _imagesByDescriptor.TryGetValue(descriptor, out image);
		}

		public ImageDescriptor AddImage(ImageItem image)
		{
			ImageDescriptor descriptor = image.GetDescriptor();
			_imagesByDescriptor[descriptor] = image;
			return descriptor;
		}

		public static ImageCache Instance = new ImageCache();
	}

	public class ImageItem : BindableBase
	{
		public static async Task<ImageItem> FromDescriptor(ImageDescriptor descriptor)
		{
			ImageItem image = null;
			if (ImageCache.Instance.TryGetImage(descriptor, out image))
			{
				return image;
			}

			StorageFile file;
			if (descriptor.Location == ImageLocation.CameraRoll)
			{
				file = await KnownFolders.CameraRoll.GetFileAsync(descriptor.FileName);
			}
			else if (descriptor.Location == ImageLocation.App)
			{
				file = await StorageFile.GetFileFromApplicationUriAsync(
					new System.Uri("ms-appx:///Images/" + descriptor.FileName)
					);
			}
			else
			{
				return null;
			}

			image = new ImageItem(file, descriptor.Location);
			ImageCache.Instance.AddImage(image);
			return image;
		}

		public ImageDescriptor GetDescriptor()
		{
			return new ImageDescriptor(Folder, Name);
		}

		private StorageFile m_file;
		private StorageItemThumbnail m_thumbNail;

		public string Name { get; set; }
		public string Path { get; set; }
		public ImageLocation Folder { get; set; }
		private BitmapImage m_photo;
		public BitmapImage Photo
		{
			get
			{
				if (m_photo == null)
				{
					var task = FetchPicture();
				}
				return m_photo;
			}
		}

		public ImageItem(StorageFile file, ImageLocation folder)
		{
			this.m_file = file;
			this.Name = file.Name;
			this.Path = file.Path;
			this.Folder = folder;
		}

		public async Task FetchPicture()
		{
			m_thumbNail = await m_file.GetThumbnailAsync(ThumbnailMode.ListView);
			if (null != m_thumbNail)
			{
				m_photo = new BitmapImage();
				m_photo.SetSource(m_thumbNail);
				OnPropertyChanged("Photo");
			}
		}

		public async Task FetchPictureOnBgThread()
		{
			m_thumbNail = await m_file.GetThumbnailAsync(ThumbnailMode.PicturesView);
		}

		public async Task<WriteableBitmap> GetPictureAsync()
		{
			IRandomAccessStream contents = await m_file.OpenAsync(FileAccessMode.Read);
			WriteableBitmap bitMap = new WriteableBitmap(100, 100);
			bitMap.SetSource(contents);
			return bitMap;
		}
	}
}
