"use strict";

const $ = require("jquery");
const escapeRegExp = require("lodash/escapeRegExp");
const userStyles = $("#user-specified-css");
const storage = require("./localStorage");
const tz = require("./libs/handlebars/tz");

const windows = $("#windows");
const chat = $("#chat");

// Default options
const options = {
	autocomplete: true,
	nickPostfix: "",
	coloredNicks: true,
	desktopNotifications: false,
	highlights: [],
	links: true,
	motd: true,
	notification: true,
	notifyAllMessages: false,
	showSeconds: false,
	statusMessages: "condensed",
	theme: $("#theme").prop("href").replace(/^themes\/(.*).css$/, "$1"), // Extracts default theme name, set on the server configuration
	media: true,
	userStyles: userStyles.text(),
};
let userOptions = JSON.parse(storage.get("settings")) || {};

for (const key in options) {
	if (userOptions[key] !== undefined) {
		options[key] = userOptions[key];
	}
}

// Apply custom CSS on page load
if (typeof userOptions.userStyles === "string" && !/[?&]nocss/.test(window.location.search)) {
	userStyles.html(userOptions.userStyles);
}

userOptions = null;

module.exports = options;

// Due to cyclical dependency, have to require it after exports
const autocompletion = require("./autocompletion");

module.exports.shouldOpenMessagePreview = function(type) {
	return type === "link" ? options.links : options.media;
};

module.exports.initialize = () => {
	module.exports.initialize = null;

	const settings = $("#settings");

	for (var i in options) {
		if (i === "userStyles") {
			settings.find("#user-specified-css-input").val(options[i]);
		} else if (i === "highlights") {
			settings.find("input[name=" + i + "]").val(options[i]);
		} else if (i === "nickPostfix") {
			settings.find("input[name=" + i + "]").val(options[i]);
		} else if (i === "statusMessages") {
			settings.find(`input[name=${i}][value=${options[i]}]`)
				.prop("checked", true);
		} else if (i === "theme") {
			$("#theme").prop("href", "themes/" + options[i] + ".css");
			settings.find("select[name=" + i + "]").val(options[i]);
		} else if (options[i]) {
			settings.find("input[name=" + i + "]").prop("checked", true);
		}
	}

	const desktopNotificationsCheckbox = $("#desktopNotifications");
	const warningUnsupported = $("#warnUnsupportedDesktopNotifications");
	const warningBlocked = $("#warnBlockedDesktopNotifications").hide();

	// Updates the checkbox and warning in settings when the Settings page is
	// opened or when the checkbox state is changed.
	// When notifications are not supported, this is never called (because
	// checkbox state can not be changed).
	const updateDesktopNotificationStatus = function() {
		if (Notification.permission === "denied") {
			desktopNotificationsCheckbox.prop("disabled", true);
			desktopNotificationsCheckbox.prop("checked", false);
			warningBlocked.show();
		} else {
			if (Notification.permission === "default" && desktopNotificationsCheckbox.prop("checked")) {
				desktopNotificationsCheckbox.prop("checked", false);
			}
			desktopNotificationsCheckbox.prop("disabled", false);
			warningBlocked.hide();
		}
	};

	// If browser does not support notifications, override existing settings and
	// display proper message in settings.
	if (("Notification" in window)) {
		warningUnsupported.hide();
		windows.on("show", "#settings", updateDesktopNotificationStatus);
	} else {
		options.desktopNotifications = false;
		desktopNotificationsCheckbox.prop("disabled", true);
		desktopNotificationsCheckbox.prop("checked", false);
	}

	settings.on("change", "input, select, textarea", function() {
		const self = $(this);
		const type = self.prop("type");
		const name = self.prop("name");

		if (type === "password") {
			return;
		} else if (type === "radio") {
			if (self.prop("checked")) {
				options[name] = self.val();
			}
		} else if (type === "checkbox") {
			options[name] = self.prop("checked");
		} else {
			options[name] = self.val();
		}

		storage.set("settings", JSON.stringify(options));

		if (name === "motd") {
			chat.toggleClass("hide-" + name, !self.prop("checked"));
		} else if (name === "statusMessages") {
			chat.toggleClass("hide-status-messages", options[name] === "hidden");
			chat.toggleClass("condensed-status-messages", options[name] === "condensed");
		} else if (name === "coloredNicks") {
			chat.toggleClass("colored-nicks", self.prop("checked"));
		} else if (name === "theme") {
			$("#theme").prop("href", "themes/" + options[name] + ".css");
		} else if (name === "userStyles") {
			userStyles.html(options[name]);
		} else if (name === "highlights") {
			var highlightString = options[name];
			options.highlights = highlightString.split(",").map(function(h) {
				return h.trim();
			}).filter(function(h) {
				// Ensure we don't have empty string in the list of highlights
				// otherwise, users get notifications for everything
				return h !== "";
			});
			// Construct regex with wordboundary for every highlight item
			const highlightsTokens = options.highlights.map(function(h) {
				return escapeRegExp(h);
			});
			if (highlightsTokens && highlightsTokens.length) {
				module.exports.highlightsRE = new RegExp("\\b(?:" + highlightsTokens.join("|") + ")\\b", "i");
			} else {
				module.exports.highlightsRE = null;
			}
		} else if (name === "nickPostfix") {
			options.nickPostfix = options[name];
		} else if (name === "showSeconds") {
			chat.find(".msg > .time").each(function() {
				$(this).text(tz($(this).parent().data("time")));
			});
			chat.toggleClass("show-seconds", self.prop("checked"));
		} else if (name === "autocomplete") {
			if (self.prop("checked")) {
				autocompletion.enable();
			} else {
				autocompletion.disable();
			}
		} else if (name === "desktopNotifications") {
			if ($(this).prop("checked") && Notification.permission !== "granted") {
				Notification.requestPermission(updateDesktopNotificationStatus);
			}
		}
	}).find("input")
		.trigger("change");
};

@@ -587,18 +587,15 @@
 f%22).
-replace
+match
 (/
-%5E
 them
@@ -605,87 +605,61 @@
 /(.*
-)
+?)%5C
 .css$/
-, %22$1%22), // Extracts default theme name, set on the server configuration
+), // TODO: Make this a data attribute in v3
 %0A%09me
@@ -766,16 +766,101 @@
 %7C%7C %7B%7D;%0A%0A
+options.theme = options.theme ? options.theme%5B1%5D : %22example%22; // TODO: Remove in v3%0A%0A
 for (con

Fix default theme not being correct