// SPDX-FileCopyrightText: 2010-2026 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later

// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later

/**
 * @file view/theme/frio/js/compose.js
 * JavaScript for the compose page (/compose).
 *
 * Handles:
 * - Link preview attachment
 * - Character counter
 * - ACL autocomplete (@-mentions)
 * - BBCode autocomplete
 * - Location button with geolocation support
 *
 * @requires jQuery
 * @requires linkPreview.js
 * @requires autocomplete.js
 */

(function ($, window, document) {
	"use strict";

	// DOM element references (cached)
	let $textarea = null;
	let locationButton = null;
	let locationInput = null;

	/**
	 * Initialize the compose page functionality.
	 */
	function init() {
		initTextarea();
		initLocation();
		initFormReset();
	}

	/**
	 * Handle form reset after successful submission and draft saving.
	 * Clears the form when a post was successfully submitted to prevent
	 * showing old content on the next visit to /compose.
	 * Also saves/restores scheduling settings as draft.
	 */
	function initFormReset() {
		const $form = $("form.comment-edit-form");

		// Check if sessionStorage is available and if a post was submitted
		// This flag is set in the submit handler below
		if (isStorageAvailable() && sessionStorage.getItem("compose_post_submitted") === "true") {
			// Clear the flag
			sessionStorage.removeItem("compose_post_submitted");

			// Clear saved draft data
			sessionStorage.removeItem("compose_draft");

			// Clear the form after a short delay to let browser autofill complete
			setTimeout(function () {
				if ($textarea && $textarea.length) {
					$textarea.val("");
					updateCharacterCounter(0);
				}

				// Also clear location if set
				if (locationInput) {
					locationInput.value = "";
					updateLocationButtonDisplay(locationButton, locationInput);
				}

				// Clear any link preview
				if (typeof window.linkPreview === "object" && window.linkPreview !== null) {
					window.linkPreview.destroy();
					window.linkPreview = null;
				}

					// Reset scheduled time
					$('[name="scheduled_at"]').val("");
				}, 50);
		} else {
			// No submission - try to restore draft if available
			restoreDraft();
		}

		// Save draft when form values change (but not on submit)
		$form.on("change.compose-draft input.compose-draft", function (e) {
			// Don't save if this is triggered by programmatic changes
			if (e.isTrigger) {
				return;
			}
			saveDraft();
		});

		// Listen for form submission
		$form.on("submit.compose", function () {
			// Mark that the form was submitted
			// This flag will be checked when the page loads next time
			if (isStorageAvailable()) {
				sessionStorage.setItem("compose_post_submitted", "true");
			}
		});
	}

	/**
	 * Check if sessionStorage is available.
	 * @returns {boolean}
	 */
	function isStorageAvailable() {
		try {
			const test = "__test__";
			sessionStorage.setItem(test, test);
			sessionStorage.removeItem(test);
			return true;
		} catch (e) {
			return false;
		}
	}

	/**
	 * Save current form state as draft to sessionStorage.
	 */
	function saveDraft() {
		if (!$textarea || !$textarea.length || !isStorageAvailable()) {
			return;
		}

		const draft = {
			body: $textarea.val(),
			location: locationInput ? locationInput.value : "",
			scheduled_at: $('[name="scheduled_at"]').val(),
		};

		try {
			sessionStorage.setItem("compose_draft", JSON.stringify(draft));
		} catch (e) {
			// Ignore storage errors (e.g., quota exceeded, private mode)
		}
	}

	/**
	 * Restore form state from sessionStorage draft.
	 */
	function restoreDraft() {
		if (!isStorageAvailable()) {
			return;
		}

		try {
			const draftJson = sessionStorage.getItem("compose_draft");
			if (!draftJson) {
				return;
			}

			const draft = JSON.parse(draftJson);

			// Restore values after a short delay to override browser autofill
			setTimeout(function () {
				if (typeof draft.body !== "undefined" && $textarea && $textarea.length) {
					$textarea.val(draft.body);
					updateCharacterCounter(draft.body.length);
				}

				// Restore location (check for undefined, not falsy, so empty string works)
				if (typeof draft.location !== "undefined" && locationInput) {
					locationInput.value = draft.location;
					updateLocationButtonDisplay(locationButton, locationInput);
					// Trigger change event so other scripts can react
					$(locationInput).trigger("change");
				}

				// Restore scheduled time (check for undefined, not falsy)
				const $scheduledAt = $('[name="scheduled_at"]');
				if (typeof draft.scheduled_at !== "undefined" && $scheduledAt.length) {
					$scheduledAt.val(draft.scheduled_at);
					// Trigger change event for datepicker plugins
					$scheduledAt.trigger("change");
				}
			}, 100);
		} catch (e) {
			// Ignore parse errors
			sessionStorage.removeItem("compose_draft");
		}
	}

	/**
	 * Initialize textarea features: link preview, autocomplete, character counter.
	 */
	function initTextarea() {
		$textarea = $("textarea[name=body]");

		if (!$textarea.length) {
			return;
		}

		// Initialize link preview plugin
		if (typeof $.fn.linkPreview === "function") {
			$textarea.linkPreview();
		}

		// Initialize ACL autocomplete (@-mentions)
		if (typeof $.fn.editor_autocomplete === "function" && typeof baseurl !== "undefined") {
			$textarea.editor_autocomplete(baseurl + "/search/acl");
		}

		// Initialize BBCode autocomplete
		if (typeof $.fn.bbco_autocomplete === "function") {
			$textarea.bbco_autocomplete("bbcode");
		}

		// Character counter - use input event to catch all changes (paste, cut, etc.)
		$textarea.on("input.compose", function () {
			updateCharacterCounter($(this).val().length);
		});

		// Initial count
		updateCharacterCounter($textarea.val().length);
	}

	/**
	 * Update the character counter display.
	 *
	 * @param {number} count - The character count
	 */
	function updateCharacterCounter(count) {
		$("#character-counter").text(count);
	}

	/**
	 * Initialize location button functionality.
	 */
	function initLocation() {
		locationButton = document.getElementById("profile-location");
		locationInput = document.getElementById("jot-location");

		if (!locationButton || !locationInput) {
			return;
		}

		// Set initial button state
		updateLocationButtonDisplay(locationButton, locationInput);

		// Bind to both input and change events for robustness
		$(locationInput)
			.on("input.compose change.compose", function () {
				updateLocationButtonDisplay(locationButton, locationInput);
			});

		// Location button click handler
		$(locationButton).on("click.compose", function () {
			handleLocationButtonClick();
		});
	}

	/**
	 * Handle the location button click.
	 */
	function handleLocationButtonClick() {
		if (!locationButton || !locationInput) {
			return;
		}

		// If location is already set, clear it
		if (locationInput.value) {
			locationInput.value = "";
			updateLocationButtonDisplay(locationButton, locationInput);
			// Trigger change event to save draft
			$(locationInput).trigger("change");
			return;
		}

		// Otherwise, try to get geolocation
		if (!("geolocation" in navigator)) {
			// Geolocation not supported - button should already be disabled
			return;
		}

		// Temporarily disable button while getting position
		locationButton.disabled = true;

		navigator.geolocation.getCurrentPosition(
			handleGeolocationSuccess,
			handleGeolocationError,
			{
				enableHighAccuracy: false,
				timeout: 10000,
				maximumAge: 600000, // 10 minutes
			}
		);
	}

	/**
	 * Handle successful geolocation retrieval.
	 *
	 * @param {GeolocationPosition} position
	 */
	function handleGeolocationSuccess(position) {
		if (!locationInput || !locationButton) {
			return;
		}

		const coords = position.coords;
		locationInput.value = coords.latitude + ", " + coords.longitude;
		locationButton.disabled = false;
		updateLocationButtonDisplay(locationButton, locationInput);
		// Trigger change event to save draft
		$(locationInput).trigger("change");
	}

	/**
	 * Handle geolocation error.
	 *
	 * @param {GeolocationPositionError} error
	 */
	function handleGeolocationError(error) {
		if (!locationButton) {
			return;
		}

		// Re-enable button so user can try again (unless geolocation is unsupported)
		if ("geolocation" in navigator) {
			locationButton.disabled = false;
		}

		updateLocationButtonDisplay(locationButton, locationInput);

		// Log error for debugging (non-critical)
		if (typeof console !== "undefined" && console.warn) {
			console.warn("Geolocation error:", error.message);
		}
	}

	/**
	 * Update the location button display based on current state.
	 *
	 * @param {HTMLButtonElement} button - The location button element
	 * @param {HTMLInputElement} input - The location input element
	 */
	function updateLocationButtonDisplay(button, input) {
		if (!button || !input) {
			return;
		}

		const hasValue = !!input.value;
		const hasGeolocation = "geolocation" in navigator;

		// Remove primary class first (will be re-added if needed)
		button.classList.remove("btn-primary");

		if (hasValue) {
			// Location is set - button clears it
			button.disabled = false;
			button.classList.add("btn-primary");
			button.title = button.dataset.titleClear || "Clear location";
		} else if (!hasGeolocation) {
			// Geolocation not supported
			button.disabled = true;
			button.title = button.dataset.titleUnavailable || "Geolocation not available";
		} else if (button.disabled) {
			// Geolocation supported but button disabled (error state)
			button.title = button.dataset.titleDisabled || "Location unavailable";
		} else {
			// Ready to get location
			button.title = button.dataset.titleSet || "Set location";
		}
	}

	// Initialize on DOM ready
	$(function () {
		init();
	});

	// Expose public API
	window.updateLocationButtonDisplay = updateLocationButtonDisplay;

})(jQuery, window, document);
// @license-end
