/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
 *
 * This source code is licensed under the license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @package FacebookCommerce
 */

/**
 * Facebook for WooCommerce - Signals helper.
 *
 * Exposes `window.fbwcsignal` so a CMP or theme integration can hold or
 * release signal delivery while keeping the plugin loaded.
 *
 * @package FacebookCommerce
 */
( function () {
	'use strict';

	var COOKIE_NAME = 'wc_facebook_signals_state';
	var STATE_ACTIVE = 'active';
	var STATE_HELD = 'held';

	/**
	 * Minimal cookie setter.
	 *
	 * @param {string} name
	 * @param {string} value
	 * @param {number} days
	 */
	function setCookie( name, value, days ) {
		var d = new Date();
		d.setTime( d.getTime() + days * 86400000 );
		document.cookie =
			name +
			'=' +
			encodeURIComponent( value ) +
			';expires=' +
			d.toUTCString() +
			';path=/;SameSite=Lax';
	}

	/**
	 * Read a cookie value.
	 *
	 * @param {string} name
	 * @return {string|null}
	 */
	function getCookie( name ) {
		var match = document.cookie.match(
			new RegExp( '(?:^|;\\s*)' + name + '=([^;]*)' )
		);
		return match ? decodeURIComponent( match[ 1 ] ) : null;
	}

	/**
	 * Update the stored signal state and sync it to PHP.
	 *
	 * @param {string} state `active` or `held`.
	 * @return {Promise} Resolves with the backend response.
	 */
	function updateState( state ) {
		setCookie( COOKIE_NAME, state, 365 );

		var params = wc_facebook_signals_params; // localized by PHP.

		return new Promise( function ( resolve, reject ) {
			var xhr = new XMLHttpRequest();
			xhr.open( 'POST', params.ajax_url, true );
			xhr.setRequestHeader(
				'Content-Type',
				'application/x-www-form-urlencoded; charset=UTF-8'
			);
			xhr.onload = function () {
				if ( xhr.status >= 200 && xhr.status < 300 ) {
					try {
						var data = JSON.parse( xhr.responseText );
						resolve( data );
					} catch ( e ) {
						reject( e );
					}
				} else {
					reject( new Error( 'AJAX failed: ' + xhr.status ) );
				}
			};
			xhr.onerror = function () {
				reject( new Error( 'Network error' ) );
			};
			xhr.send(
				'action=' +
					encodeURIComponent( params.action ) +
					'&security=' +
					encodeURIComponent( params.nonce ) +
					'&state=' +
					encodeURIComponent( state )
			);
		} );
	}

	/**
	 * Hold browser/server signals for subsequent requests.
	 *
	 * @return {Promise}
	 */
	function hold() {
		return updateState( STATE_HELD );
	}

	/**
	 * Release held signals and flush any queued browser events.
	 *
	 * @return {Promise}
	 */
	function release() {
		return updateState( STATE_ACTIVE ).then( function ( data ) {
			if (
				window.FacebookSignals &&
				window.FacebookSignals._held
			) {
				return window.FacebookSignals.release().then(
					function () {
						return data;
					},
					function () {
						return data;
					}
				);
			}

			return data;
		} );
	}

	/**
	 * Read the current signal state from the cookie.
	 *
	 * @return {string|null} `active`, `held`, or `null`.
	 */
	function getState() {
		var val = getCookie( COOKIE_NAME );
		if ( val === null ) {
			return null;
		}

		return val === STATE_ACTIVE ? STATE_ACTIVE : STATE_HELD;
	}

	window.fbwcsignal = window.fbwcsignal || {};
	window.fbwcsignal.hold = hold;
	window.fbwcsignal.release = release;
	window.fbwcsignal.getState = getState;
} )();
