

#  IMPORTS
import monju.util.streams.stringOutputStream
import monju.util.streams.stringFinder
import monju.util.zip


_UPLOAD_ID_TIMEOUT = 240*60



#  uploadCallback()
def uploadCallback(amountDone, server, amountToDo, uploadId):
	theMap              = server.getTimeoutMap("albumUploadProgress", _UPLOAD_ID_TIMEOUT)
	theMap[uploadId]    = float(amountDone) / float(amountToDo)




#  yieldData()
def yieldData(server, requestHandler, request, filePath, rootDirectory, **keys):

	#  JUST GET THE UPLOAD STATUS AS APPROPRIATE.
	parameters  = request.getParameters()
	uploadId    = parameters.get("uploadId", None)
	theMap      = server.getTimeoutMap("albumUploadProgress", _UPLOAD_ID_TIMEOUT)
	requestHandler.setPlainTextResponse()
	if uploadId is None:
		yield repr(theMap)
	else:
		result = theMap.get(uploadId, "0")
		yield str(result)



#  handlePost()
def handlePost(server, requestHandler, request, filePath, rootDirectory, **keys):

	#  DETERMINE THE UPLOAD LOCATION.
	parameters          = request.getParameters()
	firstName           = parameters["firstName"]
	lastName            = parameters["lastName"]
	albumName           = parameters["albumName"]
	uploadId            = parameters.get("uploadId", None)
	fullName            = firstName + " " + lastName
	parentDirectory     = monju.util.path.getParentDirectory(filePath)
	weddingDirectory    = monju.util.path.getParentDirectory(parentDirectory)
	albumDirectory      = monju.util.path.join(weddingDirectory, "Album", "Uploads", fullName, albumName)
	monju.util.path.createDirectory(albumDirectory)

	#  GRAB THE LENGTH.
	size = request.getContentLength()

	#  DETERMINE THE MULTIPART BOUNDARY.
	if not request.isMultipart():
		raise Exception("Non-multipart upload.")
	boundary = request.getMultipartBoundary()
	if boundary is None:
		raise Exception("No mulitipart boundary stated.")

	#  CREATE THE UPLOAD CALLBACK.
	callback = monju.lang.Thunk(uploadCallback, server=server, amountToDo=size, uploadId=uploadId)

	#  STREAM TO A TEMPORARY FILE.
	tempFile = monju.util.TemporaryFile()
	requestHandler.streamTo(tempFile, size, timeout=10, callback=callback)
	tempFile.close()

	#  NOTIFY THAT WE RECEIVED THE DATA.
	relativePath    = monju.util.path.getRelativePath(rootDirectory, filePath)
	relativePath    = relativePath.replace("\\", "/")
	parentDir       = monju.util.path.getParentDirectory(relativePath)
	uploadPage      = monju.util.path.join(parentDir, "index.psp").replace("\\", "/")
	uploadPage      = monju.util.http.encodeUrl(request.getRequestedMachineName(),
	                                            uploadPage,
	                                            firstName = firstName,
	                                            lastName  = lastName,
	                                            albumName = albumName,
	                                            uploading = "done")
	yield "<html>\n"
	yield '<meta http-equiv="refresh" content="0; url=' + uploadPage + '">\n'
	yield "<head><title>Recieved</title></head>\n"
	yield "<body>\n"
	yield "The upload completed. Click back to upload more if you are not refreshed to that page."
	yield "</body>\n</html>\n"

	#  START A THREAD TO COMPLETE THE WORK.
	monju.Thread(finishUploadWork, tempFile,
	             boundary, albumDirectory, firstName, lastName, albumName)



#  finishUploadWork()
def finishUploadWork(tempFile, boundary, albumDirectory, firstName, lastName, albumName):

	try:
		#  FIND THE MULTIPART BOUNDARIES.
		stringFinder = monju.util.streams.StringFinder(boundary)
		tempFile.streamTo(stringFinder, timeout=10)
		tempFile.close()

		#  SPLIT INTO TEMPORARY FILES.
		temporaryFiles  = []
		position        = 0
		for location in stringFinder.getLocations()[1:]:
			thisTempFile = monju.util.TemporaryFile()
			tempFile.streamTo(thisTempFile, location-position - 2)
			position = location-2
			thisTempFile.close()
			temporaryFiles.append(thisTempFile)

		#  CUT AND RENAME THE TEMPORARY FILES.
		fileNames   = []
		newPaths    = []
		for temporaryFile in temporaryFiles:
		
			#  GRAB THE FILE NAME FOR THIS PART.
			data = monju.util.file.read(temporaryFile.getFilePath())
			location = data.find("filename=")
			if location < 0:
				raise Exception("File name not found for uploaded file.")
			fileName = monju.util.string.parseArgument(data[location+9:location+2000],
			                                           includeRemainder = False)
			if fileName == "":
				return
		
			fileNames.append(fileName)
			start = data.find("\r\n\r\n", location)
			if start < 0:
				raise Exception("Data parsing: could not locate data.")
			data        = data[start+4:-2]
			outputPath  = monju.util.path.join(albumDirectory, fileName)

			#  IF THE PATH EXISTS, IF THE FILE IS THE SAME, IGNORE.
			onTry       = 1
			overWrite   = True
			while monju.util.path.exists(outputPath):
				if monju.util.file.read(outputPath) == data:
					overWrite = False
					break
				path, extension = monju.util.path.splitExtension(outputPath)
				if onTry > 1:
					path = path[:-len(str(onTry))-1]
				outputPath = path + "_" + str(onTry) + extension
				onTry += 1
			if overWrite:
				monju.util.file.write(outputPath, data)
				newPaths.append(outputPath)

		#  UNZIP ZIP FILES.
		for zipPath in newPaths:
			if not zipPath.lower().endswith(".zip"):
				continue
			directory = monju.util.TemporaryDirectory()
			monju.util.zip.unzip(zipPath, directory)
			for filePath in monju.util.path.walkFiles(directory):
				fileName    = monju.util.path.getFileName(filePath)
				outputPath  = monju.util.path.join(albumDirectory, fileName)

				#  COPY OVER THE.
				onTry       = 1
				overWrite   = True
				while monju.util.path.exists(outputPath):
					if monju.util.path.areFilesEqual(outputPath, filePath):
						overWrite = False
						break
					path, extension = monju.util.path.splitExtension(outputPath)
					if onTry > 1:
						path = path[:-len(str(onTry))-1]
					outputPath = path + "_" + str(onTry) + extension
					onTry += 1
				if overWrite:
					monju.util.file.copy(filePath, outputPath)
					newPaths.append(outputPath)

			#  REMOVE THE ZIP FOLDER.
			monju.util.path.delete(zipPath)

		#  INDEX THE JPEGS.
		monju.util.html.createIndexForJpegs(albumDirectory)
	except Exception, e:
		info = monju.util.debug.getExceptionInfo(e)
		monju.util.file.write("C:\\temp\\siteUploadErrors.txt", info, "a")

