"use strict";

const matchValue = require("match-value");
const supportsColor = require("supports-color").stderr;

let unmappedTypes = new Set([
	"im.vector.setting.breadcrumbs",
	"im.vector.setting.integration_provisioning",
	"im.vector.riot.breadcrumb_rooms", // Room selection history?
	"im.vector.web.settings",
	"m.room.bot.options", // Missing from spec: https://github.com/matrix-org/matrix-doc/issues/1409
	"opsdroid.database",
	"m.room.third_party_invite", // FIXME
	"m.room.tombstone", // FIXME
	"m.room.bridging", // FIXME
	"m.room.plumbing", // FIXME
	"org.matrix.room.preview_urls", // FIXME
	"im.vector.modular.widgets", // FIXME?
	":type", // FIXME: Temporary hack to work around invalid test event, until we have unknown-event-type warning infrastructure in place
]);

module.exports = function mapEvent(event, context) {
	// FIXME: Allow customization of this through a factor that accepts additional/overriding event mappers for different types; prefix those additional entries so that they take precedence over the default ones
	let mapper = matchValue.literal(event.type, {
		"m.room.message": require("../map-message-event"),
		"m.sticker": require("../map-message-event"), // This is really just an m.image-like message, so we handle it in one place
		"m.room.member": require("../map-member-event"),
		"m.room.encrypted": require("../map-encrypted-message-event"),
		"m.room.name": require("../map-room-name-event"),
		"m.room.topic": require("../map-topic-event"),
		"m.room.canonical_alias": require("../map-canonical-alias-event"),
		"m.presence": require("../map-presence-event"),
		"m.receipt": require("../map-receipt-event"),
		"m.typing": require("../map-typing-event"),
		"m.fully_read": require("../map-fully-read-event"),
		"m.tag": require("../map-tag-event"),
		"m.push_rules": require("../map-push-rules-event"),
		"m.room.encryption": require("../map-encryption-event"),
		"m.secret_storage.default_key": require("../map-secret-storage-default-key-event"),
		"m.cross_signing.master": require("../map-cross-signing-master-event"),
		"m.cross_signing.user_signing": require("../map-cross-signing-user-signing-event"),
		"m.cross_signing.self_signing": require("../map-cross-signing-self-signing-event"),
		"m.megolm_backup.v1": require("../map-megolm-backup-v1-event"),
		"m.room_key_request": require("../map-key-request-event"),
		"m.direct": require("../map-direct-event"),
		"m.reaction": require("../map-reaction-event"),
		"m.room.create": require("../map-room-create-event"), // FIXME: Tombstones
		"m.room.power_levels": require("../map-power-levels-event"),
		"m.room.history_visibility": require("../map-history-visibility-event"),
		"m.room.join_rules": require("../map-join-rules-event"),
		"m.room.guest_access": require("../map-guest-access-event"),
		"m.room.avatar": require("../map-room-avatar-event"),
		"m.room.related_groups": require("../map-related-groups-event"),
		"m.room.redaction": require("../map-redaction-event"),
		"m.room.server_acl": require("../map-server-acl-event"),
		_: (event, context) => {
			function call(mapper) {
				return mapper(event, context);
			}

			// Workarounds for API design hacks (eg. keyed event types for account data)
			if (event.type.startsWith("m.secret_storage.key.")) {
				return call(require("../map-secret-storage-key-event"));
			} else {
				return event;
			}
		}
	});

	let mappedEvent = mapper(event, context);

	if (mappedEvent === event && !unmappedTypes.has(event.type)) {
		throw new Error(`Event was not mapped: ${require("util").inspect(event, { depth: null, colors: supportsColor })}`);
	}

	let tests = [
		// (event.type === "m.room.message" && event.content.msgtype === "m.image"),
		// (event.type === "m.reaction"),
		(event.type === "m.room.notice"),
	];

	if (tests.some((result) => result === true)) {
	// if (event.type.startsWith("m.secret_storage.key.")) {
	// if (event.type === "m.cross_signing.master") {
		console.log("mapped event:", require("util").inspect(mappedEvent, { colors: supportsColor, depth: null }));
		throw new Error(`Break`);
	}

	return mappedEvent;
};
