<%@ WebHandler Language="VB" Class="UploadHandler" %>

Imports System
Imports System.Web
Imports System.IO
Imports System.Xml
Imports System.Text.RegularExpressions

Public Class UploadHandler
    Implements IHttpHandler
    Const _galleryPath As String = "../Gallery"
    Const _thumbnailPath As String = "Thumbnails"
    
	Public Sub ProcessRequest(ByVal context As HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
		Dim fullGalleryPath As String = context.Request.MapPath(_galleryPath)
		Dim fullThumbnailPath As String = Path.Combine(fullGalleryPath, _thumbnailPath)
		Dim baseUrl As String = New Uri(context.Request.Url, _galleryPath).AbsoluteUri
        
		'First of all, clear data uploaded at previous time.
        
		'Delete source files.
		Dim dir As New DirectoryInfo(context.Server.MapPath(_galleryPath))
		For Each file As FileInfo In dir.GetFiles()
			file.Delete()
		Next

		'Delete thumbnails.
		dir = New DirectoryInfo(context.Server.MapPath(_galleryPath) & "/Thumbnails")
		For Each file As FileInfo In dir.GetFiles()
			file.Delete()
		Next
        
		'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).
		Dim fileCount As Integer = Int32.Parse(context.Request.Form("FileCount"))
        
		Dim pointsData As New GeoData()
        
		'Save files and create placemarks.	
		'Iterate through uploaded data and save the original file, thumbnail, and description.
		For i As Integer = 1 To fileCount
			'Get source file and save it to disk.
			Dim sourceFile As HttpPostedFile = context.Request.Files("SourceFile_" & i)
			Dim fileName As String = GetSafeFileName(fullGalleryPath, Path.GetFileName(sourceFile.FileName))
			sourceFile.SaveAs(Path.Combine(fullGalleryPath, fileName))
			Dim fileSize As Integer = sourceFile.ContentLength
            
			'Get thumbnails (the single thumbnail in this code sample) and save it to disk.
			Dim thumbnail1File As HttpPostedFile = context.Request.Files("Thumbnail1_" & i)
			thumbnail1File.SaveAs(Path.Combine(fullThumbnailPath, fileName & "_SmallThumbnail.jpg"))
			Dim thumbnail2File As HttpPostedFile = context.Request.Files("Thumbnail2_" & i)
			thumbnail2File.SaveAs(Path.Combine(fullThumbnailPath, fileName & "_Thumbnail.jpg"))
            
			Dim lat As System.Nullable(Of Double) = ParseCoordinate(context.Request.Form("ExifGpsLatitude_" & i), context.Request.Form("ExifGpsLatitudeRef_" & i))
			Dim lng As System.Nullable(Of Double) = ParseCoordinate(context.Request.Form("ExifGpsLongitude_" & i), context.Request.Form("ExifGpsLongitudeRef_" & i))
            
			'escaped filename		
			Dim urlFileName As String = Uri.EscapeUriString(fileName)
            
			'create point
			Dim point As 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
			If (fileSize > 1000000) Then
				point.SizeStr = (fileSize / 1000000).ToString("N0") & " MB"
			ElseIf (fileSize > 1000) Then
				point.SizeStr = (fileSize / 1000).ToString("N0") & " KB"
			Else
				point.SizeStr = fileSize & " B"
			End If
			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)
		Next
        
		'save points to file
		Using sw As StreamWriter = File.CreateText(Path.Combine(fullGalleryPath, "description.txt"))
			sw.Write(pointsData.ToString())
			sw.Close()
		End Using
	End Sub
    
    Private Function ParseCoordinate(ByVal coordinate As String, ByVal coordinateRef As String) As System.Nullable(Of Double)
        If String.IsNullOrEmpty(coordinate) OrElse String.IsNullOrEmpty(coordinateRef) Then
            Return Nothing
        End If
        
        Dim rg As New Regex("^(\d+)/(\d+) (\d+)/(\d+) (\d+)/(\d+)$", RegexOptions.Compiled)
        Dim m As Match = rg.Match(coordinate)
        
        If m.Success AndAlso m.Groups.Count <> 7 Then
            Return Nothing
        End If
        
        Dim matches As Double() = 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" OrElse coordinateRef.ToLower() = "s" Then
            matches(0) = -1
        End If
        Return (matches(5) / matches(6) / 3600 + matches(3) / matches(4) / 60 + matches(1) / matches(2)) * matches(0)
    End Function
    
    'This method verifies whether file with such name already exists 
    'and if so, construct safe filename name (to avoid collision).	
    Private Function GetSafeFileName(ByVal galleryPath As String, ByVal fileName As String) As String
        Dim newFileName As String = fileName
        Dim j As Integer = 1
        While File.Exists(Path.Combine(galleryPath, fileName))
            newFileName = (j & "_") + fileName
            j += 1
        End While
        Return newFileName
    End Function
    
	Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
		Get
			Return False
		End Get
	End Property
    
End Class
