"use strict";

const defaultValue = require("default-value");

const diffLists = require("../diff-lists");

function mapFields(eventContent) {
	if (eventContent != null) {
		let ipLiteralSetting = eventContent.allow_ip_literals;

		return {
			// Weird logic to implement this spec requirement: "Defaults to true if missing or otherwise not a boolean."
			ipLiteralsAllowed: (ipLiteralSetting === false)
				? false
				: true,
			allowedHosts: defaultValue(eventContent.allow, []),
			deniedHosts: defaultValue(eventContent.deny, [])
		};
	} else {
		return {
			ipLiteralsAllowed: true,
			allowedHosts: [],
			deniedHosts: []
		};
	}
}

module.exports = function mapServerACLEvent(event, _context) {
	// FIXME: Number + full event
	let newFields = mapFields(event.content);
	let oldFields = mapFields(event.unsigned.prev_content);
	let deltaEvents = [];

	if (newFields.ipLiteralsAllowed !== oldFields.ipLiteralsAllowed) {
		deltaEvents.push({
			type: "accessRulesChanged",
			sender: event.sender,
			ipLiteralsAllowed: newFields.ipLiteralsAllowed
		});
	}

	let { removed: removedAllowed, added: addedAllowed } = diffLists(oldFields.allowedHosts, newFields.allowedHosts);
	let { removed: removedDenied, added: addedDenied } = diffLists(oldFields.deniedHosts, newFields.deniedHosts);

	for (let host of removedAllowed) {
		deltaEvents.push({ type: "allowedHostRemoved", sender: event.sender, hostmask: host });
	}

	for (let host of removedDenied) {
		deltaEvents.push({ type: "deniedHostRemoved", sender: event.sender, hostmask: host });
	}

	for (let host of addedAllowed) {
		deltaEvents.push({ type: "allowedHostAdded", sender: event.sender, hostmask: host });
	}

	for (let host of addedDenied) {
		deltaEvents.push({ type: "deniedHostAdded", sender: event.sender, hostmask: host });
	}

	return deltaEvents;
};
