--[[----------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2015 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remain the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

----------------------------------------------------------------------------]]--

	-- WF.core.reactive
local KSReactive = require 'KSReactive'
local KSPromises = require 'KSPromises'

	-- WF.core.utils
local WFUnknown = require 'WFUnknown'

	-- WF.core.os
local WFPlatformInfo = require 'WFPlatformInfo'

	-- WF.oz_client.utils
local WFCapabilities = require 'WFCapabilities'
local WFOzFileLock = require 'WFOzFileLock'
local WFRxHttpClient = require 'WFRxHttpClient'

-- wichitafoundation.core.logging
local WFLogger = require 'WFLogger'
local asKSPromise = require 'WFRxPromiseBridge'

--------------------------------------------------------------------------------

local exportImpLog = WFLogger 'LrmLibraryExportImp'
--:setLevel( 'debug' )

local Rx = require "Rx"
local Observable = Rx.Observable

local OzCatHelperFns = require 'OzCatHelperFns'
local OzCatHelperFns_processHttpRequestResult = OzCatHelperFns.processHttpRequestResult

local KSData = require 'KSData'

local KSTableUtils = require 'KSTableUtils'
local derefOpt = assert( KSTableUtils.derefOpt )

local LrmCatXmpDevelop = require "LrmCatXmpDevelop"

local LrmWFOzProfileUtils = require 'LrmWFOzProfileUtils'

--------------------------------------------------------------------------------

local LrmLibraryExportImp = {}

--==============================================================================

local function getMaxSupportedOriginalSize()

	local maxSupportedOriginalSize = WFCapabilities.getCapability( 'LrmConfig.maxSupportedOriginalSize' )

	if maxSupportedOriginalSize then
		return tonumber( maxSupportedOriginalSize )
	else
		return 50 * 1000 * 1000
	end

end

--------------------------------------------------------------------------------

function LrmLibraryExportImp:requestSourceFilesDownload( assetId, shouldDownloadMaster)

	local catalog = self.catalog

	exportImpLog:debugf( "THExportManager - AssetId: %s. In RequestMasterDownload", assetId )

	local resultB = KSReactive.variableB( WFUnknown.value() )
	local fileLocks = {}

	local function wrapFilePathWithFileLockP( filePathP )

		return filePathP:mapDataP( function( _, filePath )

			if not filePath then
				return 'data', filePath
			end

			local newFileLock = WFOzFileLock( catalog, filePath )
			fileLocks[ #fileLocks + 1 ] = newFileLock

			return newFileLock:lockedFilePathP()

		end )

	end

	local function obtainMasterFromOz()
		return catalog:photoInfoP( assetId )
		:mapP( function( status,docValue )
			local sha256 = derefOpt( docValue, 'develop', 'xmpCameraRaw', 'sha256' )
			-- assets imported from device will not have xmpCameraRaw attached
			if not sha256 then
				return KSPromises.resolvedPromiseP( 'data', "" )
			end
			    return LrmCatXmpDevelop.getExternalXmpDevelopP( catalog, docValue, sha256 )
		end )
		:mapP(function(status,data)
			if(status == 'data') then
			    return LrmWFOzProfileUtils.ensureProfilesExistLocallyP( catalog, assetId )
			end
			    return KSPromises.resolvedPromiseP( status,data)
		end)
		:mapP(function(status,data)
			if(status == 'data') then
				if shouldDownloadMaster then
				   return catalog:originalDataPathP(assetId, false, WFRxHttpClient.requestPriorityHigh)
		     	end
			       return KSPromises.resolvedPromiseP( 'data', "" )
			end
			   return KSPromises.resolvedPromiseP( status,data)
		end)
	end

	obtainMasterFromOz()
	:whenResolvedDo( function (status, data)

		local result = {}
		if status == 'data' then
			result =  {
				assetId = assetId,
				state = true,
				path = data
			}
		else
			result =  {
				assetId = assetId,
				state = false,
				error = data
			}
		end

		exportImpLog:debugf( "THExportManager - AssetId: %s. Master download finished. state = %s", assetId, result.state )

		resultB:set(result or {})

	end)
	:attachTo( resultB )

	return {
		valueB = resultB
	}
end

function LrmLibraryExportImp:requestFullSizeRenditionGeneration(assetId, isSpaceAsset )

    exportImpLog:debugf( "THExportManager - AssetId: %s. In requestFullSizeRenditionGeneration", assetId )

	local resultB = KSReactive.variableB( WFUnknown.value() )

	local function resultP()
		return self._renditionServer
		    :call( asKSPromise )
			:mapDataP_new( function( renditionServer )
				return renditionServer:generateFullResOnOz(assetId, isSpaceAsset)
			end)
	end

	resultP()
	:whenResolvedDo( function (status, data, headers)

		exportImpLog:debugf( "downloadFullSizeRendition resolved with = %s", data)

		if not isSpaceAsset then

			data = tostring(data)

		end

		local result

		exportImpLog:debugf( "status is %s" ,status )

		if status == 'error' then
			result = {
				assetId = assetId,
				headers = headers,
				error = true
			}
		else
			result = {
				assetId = assetId,
				headers = headers ,
				data = data
			}
		end

		exportImpLog:debugf( "Result sent ")

		resultB:set(result)

	end)
	:attachTo( resultB )

	return {
		valueB = resultB
	}
end

function LrmLibraryExportImp:downloadFullSizeRendition(photoId,downloadUrl, destPath, destFD)

	exportImpLog:debugf( "downloadFullSizeRendition %s ,%s , %s", photoId, downloadUrl,destPath)

	local catalog = self.catalog

	local optArgs = {
		requestPriority = WFRxHttpClient.requestPriorityHigh,
	    timeout = 240
	}

	-- Log and handle results

	local resultP = catalog:getBinaryP( downloadUrl, optArgs )

	resultP = resultP:observeP( function( status, data, headers )

		exportImpLog:debugf( "downloadFullSizeRendition %s resolved with %s %s", photoId, status, headers and headers.status_code )

		-- If we resolved with error
		if status == nil or status == 'error' then
			return  status,headers
		end

		OzCatHelperFns_processHttpRequestResult( catalog, status, data, headers )

	end )

	local resultB = KSReactive.variableB( WFUnknown.value() )

	local resultPP = KSPromises.callP( function( originalData )

		exportImpLog:debugf( "downloadFullSizeRendition Original data method called")

		if WFPlatformInfo.isAndroid then
			KSData.saveToFileUsingFileDescriptor( originalData, destFD )
		else
			destPath = KSData.saveToUniquelyNamedFile( originalData, destPath )
		end

		originalData:close()

		return photoId, true

	end, resultP)

	resultPP
	:whenResolvedDo( function (status,assetId, success)

    local result

		exportImpLog:debugf( "status is %s" ,status )

    if status == nil or status == 'error' then
		result = {
			assetId = assetId,
			headers = success ,
			error = true
		}
	else
		result = {
			assetId = assetId,
			success = success
		}
	end

	exportImpLog:debugf( "Result sent ")

	resultB:set(result)

	end)
	:attachTo( resultB )

	return {
 	valueB = resultB
	}
end


return LrmLibraryExportImp