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

WFRtmfpRequest.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2014 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.logging
local WFLogger = require 'WFLogger'

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local KSData = require 'KSData'
local WFCloseSupport = require 'WFCloseSupport'
local KSTableUtils = require 'KSTableUtils'

	-- RxLua
local Rx = require 'Rx'


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

local rtmfpRequestLog =  WFLogger 'WFRtmfpRequest'
--rtmfpRequestLog:enable( 'print' )

local check = assert( WFArguments.check )
KSData.registerArgumentChecker()


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

--[[!
	\class WFRtmfpRequest
	\brief This namespace provides basic RTMFP Flow services.
]]--

-- @mark WFRtmfpRequest namespace

local WFRtmfpRequest = {

	_responseGuid = false,
		-- The unique identifier for for the request, generated by the RTMFP peer
		
	_receivedOnFlowGuid = false,
		-- The Guid of the Flow that received this message
		
	_data = false,
		-- Data associated with the request
		
	_metadata = false,
		-- Metadata associated with the request
	
	_farAddress = false,
		-- Address of the sender
	
	_expectingResponse = false,
		-- Indicates how many responses the RTMFP peer expects: false, 'one', or 'many'
		
	WFCloseSupport.addCloseSupportMethods,
	
}

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

function WFRtmfpRequest:__init( request )
	
	check( 'WFRtmfpRequest', 'table' )
	
	self._responseGuid = request.guid
	self._receivedOnFlowGuid = request.flowGuid
	self._data = request.data
	self._metadata = request.metadata
	self._farAddress = request.farAddress
	
	-- Extract and clear WF-RTMFP-specific metadata fields
	
	if self._metadata then
	
		self._expectingResponse = self._metadata._expectingResponse
		self._metadata._expectingResponse = nil
		
	end
	
end

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

--[[!

	\brief Closes the object.
	
	\return void
	
--]]

function WFRtmfpRequest:close()

	check( 'WFRtmfpRequest' )
	
	if self._data then
		self._data:close()
	end
		
	self._data = nil
		
end

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

--[[!

	\brief Retrieve the data associated with the request.
	
	\return The data associated with the request.
	
--]]

function WFRtmfpRequest:getData()

	check( 'WFRtmfpRequest' )
	rtmfpRequestLog:debug( "WFRtmfpRequest:getData()" )
	return self._data
	
end

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

--[[!

	\brief Retrieve the metadata associated with the request.
	
	\return The metadata associated with the request.
	
--]]

function WFRtmfpRequest:getMetadata()

	check( 'WFRtmfpRequest' )
	rtmfpRequestLog:debug( "WFRtmfpRequest:getMetadata()" )
	return self._metadata
	
end

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

--[[!

	\brief Get the unique identifier for the Flow that the message was
	received across.

	\return string Flow Guid
	
--]]

function WFRtmfpRequest:getReceivedOnFlowGuid()

	check( 'WFRtmfpRequest' )
	return self._receivedOnFlowGuid

end

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

--[[!

	\brief Get the network address of the far sender

	\return string Network Address
	
--]]

function WFRtmfpRequest:getFarAddress()

	check( 'WFRtmfpRequest' )
	return self._farAddress

end

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

--[[!

	\brief Fetch how many responses the request expects.
	
	\return Returns false, if the request expects no response.
	Returns 'one', if the request expects a single response.
	Returns 'many', if the request expects many responses over time.
	
--]]

function WFRtmfpRequest:expectingResponse()

	check( 'WFRtmfpRequest' )
	rtmfpRequestLog:debug( "WFRtmfpRequest:expectingResponse()" )
	return self._expectingResponse
	
end

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

-- This method is called when a response is sent to the client, and updates our
-- variable that keeps track of whether or not the RTMFP peer is still expecting
-- a response.

local function updateExpectingResponse( wfRtmfpRequest )

	if wfRtmfpRequest._expectingResponse == 'one' then
	
		wfRtmfpRequest._expectingResponse = false
		
	elseif wfRtmfpRequest._expectingResponse == 'many' then
		-- No-op
	end
	
end

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

--[[!

	\brief Sends a RTMFP response back to the RTMFP peer, using the appropriate
	request GUID. Resolves when the message is sent.

	\param flow (WFRtmfpFlow) The Flow to send the data across.
	\param data (\c KSData or string) The data to send.
	\param metadata (optional, table) metadata to include with the request.
	
	\return <code>Observable</code> An observable that completes when the message
	is sent, or an error otherwise.
	
--]]

function WFRtmfpRequest:respond( flow, data, metadata )
										
	check( 'WFRtmfpRequest', 'WFRtmfpFlow', 'KSData|string', '?table' )
	
	rtmfpRequestLog:debugf( "WFRtmfpRequest:respond( data = %s )", data )
	
	metadata = metadata and KSTableUtils.shallowcopy( metadata ) or {}
	
	-- If the peer is still expecting a response, use the request Guid associated with
	-- the request in our message. Otherwise, treat this like a standard send call.
	
	if self._expectingResponse then
		metadata._responseGuid = self._responseGuid
		updateExpectingResponse( self )
	end
	
	return flow:send( data, metadata )

end

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

WFRtmfpRequest = Rx.Class( 'WFRtmfpRequest', WFRtmfpRequest )

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

return WFRtmfpRequest
