<%@ WebHandler Language="C#" Class="UploadHandler" %>

using System;
using System.Web;
using System.IO;
using System.Xml;
using System.Text.RegularExpressions;

public class UploadHandler : IHttpHandler
{
    const string _galleryPath = "../Gallery";
	const string _thumbnailPath = "Thumbnails";

	public void ProcessRequest(HttpContext context)
	{
		string fullGalleryPath = context.Request.MapPath(_galleryPath);
		string fullThumbnailPath = Path.Combine(fullGalleryPath, _thumbnailPath);
		string baseUrl = new Uri(context.Request.Url, _galleryPath).AbsoluteUri;

		//First of all, clear data uploaded at previous time.

		//Delete source files.
		DirectoryInfo dir = new DirectoryInfo(fullGalleryPath);
		foreach (FileInfo file in dir.GetFiles())
		{
			file.Delete();
		}

		//Delete thumbnails.
		dir = new DirectoryInfo(fullThumbnailPath);
		dir.Create();
		foreach (FileInfo file in dir.GetFiles())
		{
			file.Delete();
		}

		//NOTE: If you do not want to delete previously uploaded files, just
		//remove or comment out the code above.

		//Get total number of uploaded files (all files are uploaded in a single package).
		int fileCount = Int32.Parse(context.Request.Form["FileCount"]);

		GeoData pointsData = new GeoData();
			
		//Save files and create placemarks.	
		//Iterate through uploaded data and save the original file, thumbnail, and description.
		for (int i = 1; i <= fileCount; i++)
		{
			//Get source file and save it to disk.
			HttpPostedFile sourceFile = context.Request.Files["SourceFile_" + i];
			string fileName = GetSafeFileName(fullGalleryPath, Path.GetFileName(sourceFile.FileName));
			sourceFile.SaveAs(Path.Combine(fullGalleryPath, fileName));
			int fileSize = sourceFile.ContentLength;

			//Get thumbnails (the single thumbnail in this code sample) and save it to disk.
			HttpPostedFile thumbnail1File = context.Request.Files["Thumbnail1_" + i];
			thumbnail1File.SaveAs(Path.Combine(fullThumbnailPath, fileName + "_SmallThumbnail.jpg"));
			HttpPostedFile thumbnail2File = context.Request.Files["Thumbnail2_" + i];
			thumbnail2File.SaveAs(Path.Combine(fullThumbnailPath, fileName + "_Thumbnail.jpg"));

			double? lat = ParseCoordinate(context.Request.Form["ExifGpsLatitude_" + i], context.Request.Form["ExifGpsLatitudeRef_" + i]);
			double? lng = ParseCoordinate(context.Request.Form["ExifGpsLongitude_" + i], context.Request.Form["ExifGpsLongitudeRef_" + i]);
			
			//escaped filename		
			string urlFileName = Uri.EscapeUriString(fileName);
			
			//create point
			Placemark point = new Placemark();
			point.Name = fileName;
			point.SmallThumbnailUrl = baseUrl + "/" + _thumbnailPath + "/" + urlFileName + "_SmallThumbnail.jpg";
			point.ThumbnailUrl = baseUrl + "/" + _thumbnailPath + "/" + urlFileName + "_Thumbnail.jpg";
			point.ImageUrl = baseUrl + "/" + urlFileName;
			point.Latitude = lat;
			point.Longitude = lng;
			point.SizeStr=fileSize > 1000000 ? ((double)fileSize / 1000000).ToString("N0") + " MB" : 
				fileSize > 1000 ? ((double)fileSize / 1000).ToString("N0") + " KB" : fileSize + " B";
			point.Description = context.Server.HtmlEncode(context.Request.Form["Description_" + i]);
			point.Dimension = context.Request.Form["Width_" + i] + " x " + context.Request.Form["Height_" + i];

			//add point to collection		
			pointsData.Placemarks.Add(point);
		}

		//save points to file
		using (StreamWriter sw = File.CreateText(Path.Combine(fullGalleryPath, "description.txt")))
		{
			sw.Write(pointsData.ToString());
			sw.Close();
		}
	}

	private double? ParseCoordinate(string coordinate, string coordinateRef)
	{
		if (string.IsNullOrEmpty(coordinate) || string.IsNullOrEmpty(coordinateRef))
			return null;

		Regex rg = new Regex(@"^(\d+)/(\d+) (\d+)/(\d+) (\d+)/(\d+)$", RegexOptions.Compiled);
		Match m = rg.Match(coordinate);

		if (m.Success && m.Groups.Count != 7)
			return null;

		double[] matches = new double[] {1, double.Parse(m.Groups[1].Value), double.Parse(m.Groups[2].Value), double.Parse(m.Groups[3].Value), 
			double.Parse(m.Groups[4].Value), double.Parse(m.Groups[5].Value), double.Parse(m.Groups[6].Value)};
		if (coordinateRef.ToLower() == "w" || coordinateRef.ToLower() == "s")
			matches[0] = -1;
		return (matches[5] / matches[6] / 3600 + matches[3] / matches[4] / 60 + matches[1] / matches[2]) * matches[0];
	}

	//This method verifies whether file with such name already exists 
	//and if so, construct safe filename name (to avoid collision).	
	private string GetSafeFileName(string galleryPath, string fileName)
	{
		string newFileName = fileName;
		int j = 1;
		while (File.Exists(Path.Combine(galleryPath, fileName)))
		{
			newFileName = j + "_" + fileName;
			j++;
		}
		return newFileName;
	}

	public bool IsReusable
	{
		get
		{
			return false;
		}
	}

}