//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.IO;
using System.Web;
using CommunityServer.Components;
using CommunityServer.Galleries.Components;

namespace CommunityServer.Galleries.HttpHandler
{
	public class GalleryPicturesHttpHandler : IHttpHandler
	{
		public void ProcessRequest (HttpContext context)
		{
			try
			{
				CSContext csContext = CSContext.Current;

				GalleryPost DataSource = null;

				if(!Globals.IsNullorEmpty(csContext.PostName))
				{

					DataSource = GalleryPosts.GetPicture(csContext.PostName); 
					if(DataSource != null)
					{
						csContext.PostID = DataSource.PostID ;
					}
				}

				Gallery gallery = Galleries.GetGallery(csContext.ApplicationKey);
				int galleryID = gallery.SectionID;
				string imageType = null;
				int width = 0;
				int height = 0;
				DateTime modified = DateTime.Now;

				// See if we had width/height settings
				imageType = context.Request.QueryString["ImageType"];

				// Clear the response buffer
				context.Response.Clear();

				if(imageType == "temp")
				{
					//We are serving an image from the temporary storage (typically for a post preivew)
					if(context.Request.QueryString["guid"] == null)
						return;

					Guid guid = new Guid(context.Request.QueryString["guid"]);
					
					PostAttachment data = CommonDataProvider.Instance().GetTemporaryPostAttachment(guid, galleryID, csContext.User.UserID);

					GalleryImageSettings settings = gallery.GetPictureDetailsSettings();

					ImageHandling.GetMaintainedRatio(data.Height, data.Width, settings);
					string filename = string.Concat(GalleryConfiguration.Instance().CacheSettings.GetLocalFileName(gallery.SectionID, guid.ToString() ) ,".jpg");
					ImageHandling.ScalePicture(filename, gallery, data, settings);

					// Send the picture
					context.Response.ContentType = "image/jpeg";
					context.Response.WriteFile(filename, true);
					context.Response.AddFileDependency(filename);

					//clean up our mess
					if(!File.Exists(filename) )
						File.Delete(filename);

					return; //we need to return so we dont cache the temp image
				}

				if(imageType == "watermark")
				{
					string filename = GalleryConfiguration.Instance().CacheSettings.GetLocalWatermarkFileName(galleryID);
					context.Response.ContentType = "image/jpeg";
					context.Response.WriteFile(filename, true);
					context.Response.AddFileDependency(filename);
					return; //we need to return so we dont cache the watermark
				}

				int pictureID = csContext.PostID;
				if(DataSource == null)
					DataSource = GalleryPosts.GetPicture(pictureID); 

				try
				{
					Referral r = new Referral();
					r.SettingsID = gallery.SettingsID;
					r.SectionID = galleryID;
					r.PostID = pictureID;
					Referrals.AddToQueue(context,gallery.ReferralFilter,r);
				}
				catch{}

				if(!CanUserView(DataSource, csContext.User)) 
					Globals.Return404(context);


				if(context.Request.QueryString["Width"] != null)
					width = int.Parse(context.Request.QueryString["Width"]);
				if(context.Request.QueryString["Height"] != null)
					height = int.Parse(context.Request.QueryString["Height"]);


				if (imageType == "original" && !gallery.HasWatermark && !gallery.HasMaxSize)
				{
					// Show the original image
					PostAttachment data = GalleryPosts.GetPictureData(DataSource);
					modified = data.DateCreated;
					context.Response.AddFileDependency(context.Server.MapPath(data.FileName));

					// Send the picture
					context.Response.ContentType = data.ContentType + "; name=\"" + context.Server.UrlEncode(data.FileName) + "\"";
					context.Response.AddHeader("Content-disposition", "inline; filename=\"" + context.Server.UrlEncode(data.FileName) + "\"");

					byte[] buffer = new byte[256 * 1024];
					int bytes;

					while ((bytes = data.Content.Read(buffer, 0, 256 * 1024)) > 0)
						context.Response.OutputStream.Write(buffer, 0, bytes);
					context.Response.OutputStream.Flush();
				}
				else if (imageType != null)
				{
					string filename = "";

					// Show a cached scaled image
					if (imageType == "thumb")
						filename = GalleryConfiguration.Instance().CacheSettings.GetLocalThumbnailFileName(DataSource);
					else if (imageType == "secondarythumb")
						filename = GalleryConfiguration.Instance().CacheSettings.GetLocalSecondaryThumbnailFileName(DataSource);
					else if (imageType == "original")
					{
						PostAttachment data = GalleryPosts.GetPictureData(DataSource);
						filename = GalleryConfiguration.Instance().CacheSettings.GetLocalFileName(DataSource, data.Width, data.Height);
					}

					//If the file doesnt exist try to create it
					if (!File.Exists(filename))
					{
						if (DataSource.IsPicture)
						{
							GalleryImageSettings settings = null;
							if (imageType == "thumb")
								settings = DataSource.Gallery.GetThumbnailSettings();
							else if (imageType == "secondarythumb")
								settings = DataSource.Gallery.GetSecondaryThumbnailSettings();
							else if (imageType == "original")
							{
								//Apply any gallery max size to the image settings
								int oWidth = (DataSource.Gallery.HasMaxX) ? DataSource.Gallery.MaxX : DataSource.Attachment.Width;
								int oHeight = (DataSource.Gallery.HasMaxY) ? DataSource.Gallery.MaxY : DataSource.Attachment.Height;
								int oQuality = (oWidth == DataSource.Attachment.Width && oHeight == DataSource.Attachment.Height) ? -1 : DataSource.Gallery.Quality;
								settings = new GalleryImageSettings(oWidth, oHeight, oQuality, true, false, false);
							}
							ImageHandling.GetMaintainedRatio(DataSource, settings);
							ImageHandling.ScalePicture(filename, DataSource, settings);
						}
					}

					modified = File.GetCreationTime(filename);

					// Send the file
					context.Response.ContentType = "image/jpeg";
					context.Response.WriteFile(filename, true);
					context.Response.AddFileDependency(filename);
				}
				else
				{
					// Show a cached scaled image
					string filename = GalleryConfiguration.Instance().CacheSettings.GetLocalFileName(DataSource, width, height);

					//If the file doesnt exist try to create it
					if (!File.Exists(filename))
					{
						if (DataSource.IsPicture)
						{
							GalleryImageSettings settings = null;
							settings = new GalleryImageSettings(width, height, DataSource.Gallery.PictureDetailsQuality, true, false, false);
							ImageHandling.GetMaintainedRatio(DataSource, settings);
							ImageHandling.ScalePicture(filename, DataSource, settings);
						}

					}

					modified = File.GetCreationTime(filename);

					// Send the file
					context.Response.ContentType = "image/jpeg";
					context.Response.WriteFile(filename, true);
					context.Response.AddFileDependency(filename);
				}

				// Browser cache settings
				context.Response.Cache.SetCacheability(HttpCacheability.Public);
				context.Response.Cache.SetLastModified(modified);
				context.Response.Cache.SetAllowResponseInBrowserHistory(true);
				context.Response.Cache.SetValidUntilExpires(true);
				context.Response.Cache.VaryByParams["PostID"] = true;
				context.Response.Cache.VaryByParams["PostName"] = true;
				context.Response.Cache.VaryByParams["Width"] = true;
				context.Response.Cache.VaryByParams["Height"] = true;
				context.Response.Cache.VaryByParams["ImageType"] = true;
			}
			catch {}
		}

		public bool IsReusable { get { return false; } }

		protected static bool CanUserView(GalleryPost post, User user)
		{
            if (post.Section.IsOwner(user.Username))
                return true;
		    
			//admins can always see a post
			if(Permissions.ValidatePermissions(post.Section,Permission.Post, user))
				return true;
			
			//Permissions.AccessCheck(post.Section,Permission.View, user);
			if(!Permissions.ValidatePermissions(post.Section,Permission.View, user))
				return false;

			if(!post.IsPostEnabled)
				return false;

			if(!post.Gallery.IsActive)
				return false;

			return true;
		}

	}
}
