/* ======================== conds ======================== */
static tsk_bool_t _fsm_cond_get_local_candidates(tsip_dialog_invite_t* self, tsip_message_t* message)
{
	if(self->supported.ice){
		tsk_bool_t use_ice = tsk_false;
		// "action->media.type" will be defined for locally initiated media update
		tmedia_type_t new_media = TSIP_DIALOG(self)->curr_action ? TSIP_DIALOG(self)->curr_action->media.type : tmedia_none;

		if(message && TSIP_MESSAGE_HAS_CONTENT(message) && tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
			// If this code is called this means that we are the "answerer"
			// only gets the candidates if ICE is enabled and the remote peer supports ICE
			tsdp_message_t* sdp_ro;
			const tsdp_header_M_t* M;
			int index;
			if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
				TSK_DEBUG_ERROR("Failed to parse remote sdp message");
				return tsk_false;
			}
			
			index = 0;
			while((M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp_ro, tsdp_htype_M, index++))){
				if(!tsdp_header_M_findA(M, "candidate")){
					use_ice = tsk_false; // do not use ICE if at least on media is ICE-less (e.g. MSRP)
					break;
				}
				use_ice = tsk_true; // only use ICE if there is a least one media line
			}
			
			new_media = tmedia_type_from_sdp(sdp_ro);

			TSK_OBJECT_SAFE_FREE(sdp_ro);
		}
		else if(!message){
			// we are the "offerer" -> use ICE only for audio or video medias (ignore ice for MSRP)
			use_ice = (new_media & tmedia_audio) || (new_media & tmedia_video);
		}

		if(use_ice){
			if(!self->ice.ctx_audio && !self->ice.ctx_video){ // First time
				return tsk_true;
			}
			else{
				if(self->ice.media_type != new_media){
					return tsk_true;
				}
				return !tsip_dialog_invite_ice_got_local_candidates(self);
			}
		}
	}
	return tsk_false;
}
// Current -> (iINVITE) -> Current
static int x0500_Current_2_Current_X_iINVITE(va_list *app)
{
	int ret;
	tsip_dialog_invite_t *self;
	const tsip_action_t* action;
	const tsip_message_t *message;

	self = va_arg(*app, tsip_dialog_invite_t *);
	message = va_arg(*app, const tsip_message_t *);
	action = va_arg(*app, const tsip_action_t *);

	self->is_client = tsk_false;
	ret = tsip_dialog_invite_ice_save_action(self, _fsm_action_iINVITE, action, message);
	
	// Cancel without notifying ("silent mode") and perform the operation right now ("sync mode")
	tsip_dialog_invite_ice_cancel_silent_and_sync_ctx(self);

	// set remote candidates
	if(TSIP_MESSAGE_HAS_CONTENT(message)){
		if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
			tsdp_message_t* sdp_ro;
			if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
				TSK_DEBUG_ERROR("Failed to parse remote sdp message");
				return -2;
			}
			// create ICE context
			if((ret = tsip_dialog_invite_ice_create_ctx(self, tmedia_type_from_sdp(sdp_ro)))){
				TSK_DEBUG_ERROR("tsip_dialog_invite_ice_create_ctx() failed");
				return ret;
			}
			ret = tsip_dialog_invite_ice_process_ro(self, sdp_ro, tsk_true);
			TSK_OBJECT_SAFE_FREE(sdp_ro);
		}
		else{
			TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message));
			return -3;
		}
	}

	// For now disable ICE timers until we send the 2xx and receive the ACK
	ret = tsip_dialog_invite_ice_timers_set(self, -1);

	// Start ICE
	ret = tsip_dialog_invite_ice_start_ctx(self);

	return ret;
}
// Started -> (iINVITE) -> Started
static int x0500_Current_2_Current_X_iINVITE(va_list *app)
{
	int ret;
	tsip_dialog_invite_t *self;
	const tsip_action_t* action;
	const tsip_message_t *message;

	self = va_arg(*app, tsip_dialog_invite_t *);
	message = va_arg(*app, const tsip_message_t *);
	action = va_arg(*app, const tsip_action_t *);

	self->is_client = tsk_false;
	ret = tsip_dialog_invite_ice_save_action(self, _fsm_action_iINVITE, action, message);
	
	// set remote candidates
	if(TSIP_MESSAGE_HAS_CONTENT(message)){
		if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){
			tsdp_message_t* sdp_ro;
			if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){
				TSK_DEBUG_ERROR("Failed to parse remote sdp message");
				return -2;
			}
			// create ICE context
			if((ret = tsip_dialog_invite_ice_create_ctx(self, tmedia_type_from_sdp(sdp_ro)))){
				TSK_DEBUG_ERROR("tsip_dialog_invite_ice_create_ctx() failed");
				return ret;
			}
			ret = tsip_dialog_invite_ice_process_ro(self, sdp_ro, tsk_true);
			TSK_OBJECT_SAFE_FREE(sdp_ro);
		}
		else{
			TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message));
			return -3;
		}
	}

	// Start ICE
	ret = tsip_dialog_invite_ice_start_ctx(self);

	return ret;
}