'use strict';

const elementSize = require("element-size");
const sortDockable = require("./util/sort-dockables");

function px(pixels) {
	return `${pixels}px`;
}

module.exports = {
	init: function() {
		let dockableAPI = {
			isActive: () => {
				return (this.opts.dockableContainer != null);
			},
			stack: [],
			fillElement: null,
			recalculateLayout: () => {
				dockableAPI.stack.forEach((item, i) => {
					item.stackIndex = i;
				});

				let orderedStack = dockableAPI.stack.slice().sort(sortDockable);

				let reservedLeft = 0;
				let reservedRight = 0;
				let reservedTop = 0;
				let reservedBottom = 0;

				orderedStack.forEach((item) => {
					let element = item.tag.root;

					/* We set the positioning to absolute *before* attempting
					 * to obtain the element size - this way, we can be sure
					 * that the element won't try to stretch to its container.
					 * Instead, it'll be auto-sized, which is exactly what we
					 * want. */
					element.style.position = "absolute";

					let [width, height] = elementSize(element);

					if (item.heightHint != null) {
						height = item.heightHint;
					}

					if (item.widthHint != null) {
						width = item.widthHint;
					}

					// FIXME: Should the following really be errors?
					if ((item.side === "left" || item.side === "right") && width === 0) {
						throw new Error("Cannot horizontally dock an element without a width; you may need to specify a dock-width");
					} else if ((item.side === "top" || item.side === "bottom") && height === 0) {
						throw new Error("Cannot vertically dock an element without a height; you may need to specify a dock-height");
					}

					if (item.side === "left") {
						Object.assign(element.style, {
							left: px(reservedLeft),
							top: px(reservedTop),
							bottom: px(reservedBottom)
						});

						delete element.style.right;

						reservedLeft += width;
					} else if (item.side === "right") {
						Object.assign(element.style, {
							right: px(reservedRight),
							top: px(reservedTop),
							bottom: px(reservedBottom)
						});

						delete element.style.left;

						reservedRight += width;
					} else if (item.side === "top") {
						Object.assign(element.style, {
							left: px(reservedLeft),
							right: px(reservedRight),
							top: px(reservedTop)
						});

						delete element.style.bottom;

						reservedTop += height;
					} else if (item.side === "bottom") {
						Object.assign(element.style, {
							left: px(reservedLeft),
							right: px(reservedRight),
							bottom: px(reservedBottom)
						});

						delete element.style.top;

						reservedBottom += height;
					}
				})

				let item = dockableAPI.fillElement;

				if (item != null) {
					let element = item.root;

					Object.assign(element.style, {
						position: "absolute",
						left: px(reservedLeft),
						right: px(reservedRight),
						top: px(reservedTop),
						bottom: px(reservedBottom)
					});
				}
			}
		}

		this._uikitDockableContainer = dockableAPI;

		this.on("mount", () => {
			if (dockableAPI.isActive()) {
				dockableAPI.recalculateLayout();
			}
		})
	}
}
