"use strict";

const matchValue = require("match-value");

const operations = require("../operations");
const typeOf = require("../type-of");
const NoChange = require("./util/no-change");

// FIXME: Generalize to all predicate lists?

function createHandler(type) {
	let subItemProperty = matchValue(type, {
		notCondition: "condition",
		notExpression: "expression"
	});

	return function flattenNotPredicates(expression) {
		// Flattens multiple levels of like-typed not(...) wrappers, ending up with a logically equivalent subtree
		//		`notCondition(condition)` -> `notCondition(condition)`
		//		`notCondition(notCondition(condition))` -> `condition`
		//		`notCondition(notCondition(notCondition(condition)))` -> `notCondition(condition)`
		//		etc.
		let notLevels = 0;
		let currentItem = expression;
	
		while(typeOf(currentItem) === type) {
			notLevels += 1;
			currentItem = currentItem[subItemProperty];
		}

		if (notLevels === 1) {
			return NoChange;
		} else {
			let hasNot = (notLevels % 2) === 1;

			if (hasNot) {
				return operations.not(currentItem);
			} else {
				return currentItem;
			}
		}
	};
}

module.exports = {
	name: "flatten-not-predicates",
	category: [ "readability" ],
	visitors: {
		notExpression: createHandler("notExpression"),
		notCondition: createHandler("notCondition")
	}
};
