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

ADOBE CONFIDENTIAL
------------------
Copyright 2020 Adobe Inc
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.

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

local Rx = require "Rx"

local WFCrypto = require "WFCrypto"
local WFCatP2PIdentityManager = require "WFCatP2PIdentityManager"

local KSData = require "KSData"

	-- WF.web
local WFBonjour = require "WFBonjour"
local WFRxHttpServer = require "WFRxHttpServer"

local runUntilDone = require 'WFRxRunUntilDone'

local LriP2PServiceModel = {}

function LriP2PServiceModel.makeModel( wfCatalog, name, options )

	local _bonjourSub
	local _bonjourHandle
	local _bonjourService
	local _httpServer
	local _catalogHash

	local catalogId = KSData.make( wfCatalog:ozCatalogSpec():catalogId() )
	_catalogHash = catalogId:digest( 'SHA224' )

	local requestIdentity = WFCatP2PIdentityManager.getOrRequestIdentity( wfCatalog, _catalogHash, options )
		:map( function( identityFile, password, caCertificateFile )

			local cert, privateKey = WFCrypto.readP12( identityFile, password )

			local serverOptions = {
				listening_ports = "0s", -- ephemeral port with TLS
				wf_certificate = cert,
				wf_certificate_key = privateKey,
				ssl_ca_file = caCertificateFile,
				ssl_verify_peer = "yes"
			}

			_httpServer = WFRxHttpServer.start( 'LriP2PHttpServerHandlers.startRequest', serverOptions, wfCatalog )

			local ports = _httpServer:getPorts()

			if not ports or not next( ports ) then
				error( 'could not start P2P HTTPS server' )
			end

			_bonjourSub = WFBonjour.start()
				:subscribe()

			_bonjourService = WFBonjour.publishService( name, WFBonjour.kServiceTypeLightroomP2P, ports[ 1 ] )
			:filter( function( result )
				_bonjourHandle = result.data
				return( result.success )
			end )
			:subscribe( )

			return {
				ports = ports,
				identityFile = identityFile,
				password = password,
				caCertificateFile = caCertificateFile
			}

		end )
		

	return {

		value = requestIdentity
			:concat( Rx.Observable.never() ),

		close = function()

			if _bonjourService then
				WFBonjour.stopPublishService( _bonjourHandle )
					:map( function() 
						_bonjourService:dispose()
						_bonjourService = nil
						return nil;
					end )
					:call( runUntilDone )
			end

			if _httpServer then
				_httpServer:close()
				_httpServer = nil
			end

			if _bonjourSub then
				WFBonjour.stop()
					:call( runUntilDone )

				_bonjourSub:dispose()
				_bonjourSub  = nil
				_bonjourHandle = nil

			end


		end
	}

end

return LriP2PServiceModel