'use strict';

exports.__esModule = true;
exports.default = createObservableStateManager;

var _ramda = require('ramda');

var _ramda2 = _interopRequireDefault(_ramda);

var _mobx = require('mobx');

var _parser = require('../parser');

var _validateContent = require('../ingredients/validateContent');

var _validateContent2 = _interopRequireDefault(_validateContent);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var suggestReferenceFromTree = _ramda2.default.uncurryN(2, function (ingredients) {
	return _ramda2.default.pipe(_ramda2.default.chain(_ramda2.default.pluck('mentions')), _ramda2.default.tap(function (mentions) {
		return console.log('mentions for suggestion', mentions);
	}), _ramda2.default.unnest, _ramda2.default.reject(_ramda2.default.isNil), _ramda2.default.map(_ramda2.default.head), // Just the requested ingredient ID
	_ramda2.default.difference(_ramda2.default.__, _ramda2.default.pluck('id', ingredients)), // Only IDs that are yet to be used
	_ramda2.default.head // First pick
	);
});

function createObservableIngredientVariation(ingredient, _ref) {
	var _ref$enabled = _ref.enabled,
	    enabled = _ref$enabled === undefined ? true : _ref$enabled,
	    rawContent = _ref.rawContent;

	return (0, _mobx.observable)({
		enabled: enabled,
		rawContent: rawContent,
		get result() {
			var transform = (0, _validateContent.transformerForType)(ingredient.type);
			return _ramda2.default.tryCatch(transform, _ramda2.default.objOf('error'))(this.rawContent);
		},
		toggleEnabled: (0, _mobx.action)(function () {
			this.enabled = !this.enabled;
		}),
		adjustRawContent: (0, _mobx.action)(function (adjuster) {
			this.rawContent = adjuster(this.rawContent);
		}),
		adjustContent: (0, _mobx.action)(function (adjuster) {
			var result = this.result;
			if (result.content) {
				adjuster(result.content);
				this.rawContent = (0, _validateContent.stringRepresenterForType)(ingredient.type, result.content);
			}
		}),
		editPath: (0, _mobx.action)(function (path, editor) {
			this.adjustContent(function (content) {
				var _ref2 = path.length == 1 ? [content, path[0]] : [_ramda2.default.path(initialPath, content), _ramda2.default.last(path)],
				    parent = _ref2[0],
				    key = _ref2[1];

				if (parent) {
					editor(parent, key);
				} else {
					// Warn user about incorrect key path?
				}
			});
		}),
		adjustPath: (0, _mobx.action)(function (path, adjuster) {
			this.editPath(path, function (parent, key) {
				parent[key] = adjuster(parent[key]);
			});
		})
	});
}

function createObservableIngredient(target) {
	var ingredient = (0, _mobx.observable)({
		id: target.id,
		type: target.type,
		addVariation: _mobx.action.bound(function (variation) {
			this.variations.push(createObservableIngredientVariation(this, variation));
		}),
		addNewVariation: _mobx.action.bound(function (variation) {
			this.addVariation({
				rawContent: ''
			});
		}),
		get flattenedResult() {
			var flattened = {
				type: this.type,
				variationReference: _ramda2.default.last(this.variations)
			};

			if (this.type == 'json') {
				flattened.content = this.variations.reduce(function (combined, variation) {
					// Use only if enabled
					if (!variation.enabled) {
						return combined;
					}
					// Skip if no content
					var result = variation.result;
					if (result.content == null) {
						return combined;
					}
					// Merge into combined JSON object
					return Object.assign(combined, result.content);
				}, {});
			} else {
				var variation = _ramda2.default.findLast(_ramda2.default.propEq('enabled', true), this.variations);
				if (variation) {
					flattened.content = variation.result.content;
				}
			}

			return flattened;
		}
	});

	(0, _mobx.extendObservable)(ingredient, {
		variations: target.variations.map(_ramda2.default.curry(createObservableIngredientVariation)(ingredient))
	});

	return ingredient;
}

function createObservableStateManager() {
	var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
	    _ref3$content = _ref3.content,
	    content = _ref3$content === undefined ? '' : _ref3$content,
	    _ref3$destinationID = _ref3.destinationID,
	    destinationID = _ref3$destinationID === undefined ? 'foundation' : _ref3$destinationID,
	    _ref3$destinationDevi = _ref3.destinationDevice,
	    destinationDevice = _ref3$destinationDevi === undefined ? 'phone' : _ref3$destinationDevi,
	    _ref3$ingredients = _ref3.ingredients,
	    ingredients = _ref3$ingredients === undefined ? [] : _ref3$ingredients,
	    _ref3$scenarios = _ref3.scenarios,
	    scenarios = _ref3$scenarios === undefined ? [{}] : _ref3$scenarios,
	    _ref3$activeScenarioI = _ref3.activeScenarioIndex,
	    activeScenarioIndex = _ref3$activeScenarioI === undefined ? 0 : _ref3$activeScenarioI;

	return (0, _mobx.observable)({
		content: content,
		destinationID: destinationID,
		destinationDevice: destinationDevice,
		ingredients: ingredients.map(createObservableIngredient),
		scenarios: scenarios,
		activeScenarioIndex: activeScenarioIndex,

		get json() {
			return {
				body: this.content,
				ingredients: (0, _mobx.toJS)(this.ingredients)
			};
		},
		set json(_ref4) {
			var _ref4$body = _ref4.body,
			    body = _ref4$body === undefined ? '' : _ref4$body,
			    _ref4$ingredients = _ref4.ingredients,
			    ingredients = _ref4$ingredients === undefined ? [] : _ref4$ingredients;

			this.content = body;
			this.ingredients = ingredients.map(createObservableIngredient);
		},

		get contentTree() {
			return (0, _parser.parseInput)(this.content);
		},
		get activeScenario() {
			return this.scenarios[this.activeScenarioIndex];
		},
		get activeIngredients() {
			var activeScenario = this.activeScenario;
			return this.ingredients.reduce(function (object, _ref5) {
				var id = _ref5.id,
				    flattenedResult = _ref5.flattenedResult;

				object[id] = flattenedResult;
				return object;
			}, {});
		},
		activeVariationForIngredientAtIndex: function activeVariationForIngredientAtIndex(index) {
			var ingredient = this.ingredients[index];
			if (ingredient && ingredient.variations.length > 0) {
				var activeScenario = this.activeScenario;
				return ingredient.variations[_ramda2.default.propOr(0, ingredient.id, activeScenario)];
			}
		},

		addNewIngredient: _mobx.action.bound(function () {
			var suggestedID = suggestReferenceFromTree(this.ingredients, this.contentTree);
			this.ingredients.push(createObservableIngredient({
				id: _ramda2.default.defaultTo('untitled', suggestedID),
				type: 'text',
				variations: [{
					rawContent: ''
				}]
			}));
		}),
		onRemoveIngredientAtIndex: _mobx.action.bound(function (index) {
			this.ingredients.splice(index, 1);
		})
	});
}
module.exports = exports['default'];