"use strict";
const getTemplate = require("./get-template");
const ObjectLiteral = require("./object");
const camelCase = require("./camel-case");
const unCamelCase = require("./un-camel-case");
const Literal = require("./literal");
const postcss = require("postcss");

function forEach (arr, callback) {
	arr && arr.forEach(callback);
}

const replaceProp = (fn) => (value) => (
	value.replace(/(\(\s*)(.*?)(\s*:)/g, (s, prefix, prop, suffix) => (
		prefix + fn(prop) + suffix
	))
);
const camelCaseProp = replaceProp(camelCase);
const unCamelCaseProp = replaceProp(unCamelCase);

function defineRaws (node, prop, prefix, suffix, props) {
	if (!props) {
		props = {};
	}
	const descriptor = {
		enumerable: true,
		get: () => (
			node[prop]
		),
		set: (value) => {
			node[prop] = value;
		},
	};

	if (!props.raw) {
		props.raw = descriptor;
	} else if (props.raw === "camel") {
		props.raw = {
			enumerable: true,
			get: () => (
				camelCase(node[prop])
			),
			set: (value) => {
				node[prop] = unCamelCase(value);
			},
		};
	}

	props.value = descriptor;

	node.raws[prop] = Object.defineProperties({
		prefix,
		suffix,
	}, props);
}

class objectParser {
	constructor (input) {
		this.input = input;
	}
	parse (node) {
		const root = postcss.root({
			source: {
				input: this.input,
				start: node.loc.start,
			},
		});
		root.raws.node = node;
		const obj = new ObjectLiteral({
			raws: {
				node,
			},
		});
		root.push(obj);
		this.process(node, obj);
		this.sort(root);
		this.raws(root);

		const startNode = root.first.raws.node;
		const endNode = root.last.raws.node;

		const start = {
			line: startNode.loc.start.line,
		};

		let before = root.source.input.css.slice(startNode.start - startNode.loc.start.column, startNode.start);
		if (/^\s+$/.test(before)) {
			start.column = 1;
		} else {
			before = "";
			start.column = startNode.loc.start.column;
		}

		root.first.raws.before = before;
		root.source.input.css = before + root.source.input.css.slice(startNode.start, endNode.end);
		root.source.start = start;

		this.root = root;
	}

	process (node, parent) {
		[
			"leadingComments",
			"innerComments",
			"trailingComments",
		].forEach(prop => {
			forEach(node[prop], child => {
				this.source(child, this.comment(child, parent));
			});
		});

		const child = (this[node.type] || this.literal).apply(this, [node, parent]);
		this.source(node, child);
		return child;
	}
	source (node, parent) {
		parent.source = {
			input: this.input,
			start: node.loc.start,
			end: node.loc.end,
		};
		return parent;
	}
	raws (parent, node) {
		const source = this.input.css;
		parent.nodes.forEach((child, i) => {
			if (i) {
				child.raws.before = source.slice(parent.nodes[i - 1].raws.node.end, child.raws.node.start).replace(/^\s*,+/, "");
			} else if (node) {
				child.raws.before = source.slice(node.start, child.raws.node.start).replace(/^\s*{+/, "");
			}
		});
		if (node) {
			let semicolon;
			let after;
			if (parent.nodes.length) {
				after = source.slice(parent.last.raws.node.end, node.end).replace(/^\s*,+/, () => {
					semicolon = true;
					return "";
				});
			} else {
				after = source.slice(node.start, node.end).replace(/^\s*{/, "");
			}
			parent.raws.after = after.replace(/}+\s*$/, "");
			parent.raws.semicolon = semicolon || false;
		}
	}

	sort (node) {
		node.nodes = node.nodes.sort((a, b) => (
			a.raws.node.start - b.raws.node.start
		));
	}

	getNodeValue (node, wrappedValue) {
		const source = this.input.css;
		let rawValue;
		let cookedValue;
		switch (node.type) {
			case "Identifier": {
				const isCssFloat = node.name === "cssFloat";
				return {
					prefix: "",
					suffix: "",
					raw: isCssFloat && node.name,
					value: isCssFloat ? "float" : node.name,
				};
			}
			case "StringLiteral": {
				rawValue = node.extra.raw.slice(1, -1);
				cookedValue = node.value;
				break;
			}
			case "TemplateLiteral": {
				rawValue = getTemplate(node, source);
				break;
			}
			default: {
				rawValue = source.slice(node.start, node.end);
				break;
			}
		}
		const valueWrap = wrappedValue.split(rawValue);
		return {
			prefix: valueWrap[0],
			suffix: valueWrap[1],
			value: cookedValue || rawValue,
		};
	}

	ObjectExpression (node, parent) {
		forEach(node.properties, child => {
			this.process(child, parent);
		});
		this.sort(parent);
		this.raws(parent, node);
		return parent;
	}

	ObjectProperty (node, parent) {
		const source = this.input.css;
		let between = source.indexOf(":", node.key.end);
		const rawKey = source.slice(node.start, between).trimRight();
		const rawValue = source.slice(between + 1, node.end).trimLeft();
		between = source.slice(node.start + rawKey.length, node.end - rawValue.length);
		const key = this.getNodeValue(node.key, rawKey);
		if (node.value.type === "ObjectExpression") {
			let rule;
			if (/^@(\S+)(\s*)(.*)$/.test(key.value)) {
				const name = RegExp.$1;
				const afterName = RegExp.$2;
				const params = RegExp.$3;
				const atRule = postcss.atRule({
					name: unCamelCase(name),
					raws: {
						afterName: afterName,
					},
					nodes: [],
				});
				defineRaws(atRule, "name", key.prefix + "@", params ? "" : key.suffix, {
					raw: "camel",
				});
				if (params) {
					atRule.params = unCamelCaseProp(params);
					defineRaws(atRule, "params", "", key.suffix, {
						raw: {
							enumerable: true,
							get: () => (
								camelCaseProp(atRule.params)
							),
							set: (value) => {
								atRule.params = unCamelCaseProp(value);
							},
						},
					});
				}
				rule = atRule;
			} else {
				// rule = this.rule(key, keyWrap, node.value, parent);
				rule = postcss.rule({
					selector: key.value,
				});
				defineRaws(rule, "selector", key.prefix, key.suffix);
			}
			raw(rule);
			this.ObjectExpression(node.value, rule);
			return rule;
		}

		const value = this.getNodeValue(node.value, rawValue);

		if (key.value[0] === "@") {
			const atRule = postcss.atRule({
				name: unCamelCase(key.value),
				params: value.value,
			});
			defineRaws(atRule, "name", key.prefix, key.suffix, {
				raw: "camel",
			});

			defineRaws(atRule, "params", value.prefix, value.suffix);
			raw(atRule);
			return atRule;
		} else {
			let decl;
			if (key.raw) {
				decl = postcss.decl({
					prop: key.value,
					value: value.value,
					raws: {
						prop: key,
					},
				});
			} else {
				decl = postcss.decl({
					prop: unCamelCase(key.value),
					value: value.value,
				});

				defineRaws(decl, "prop", key.prefix, key.suffix, {
					raw: "camel",
				});
			}

			defineRaws(decl, "value", value.prefix, value.suffix);
			raw(decl);
			return decl;
		}

		function raw (postcssNode) {
			postcssNode.raws.between = between;
			postcssNode.raws.node = node;
			parent.push(postcssNode);
		}
	}

	literal (node, parent) {
		const literal = new Literal({
			text: this.input.css.slice(node.start, node.end),
			raws: {
				node,
			},
		});
		parent.push(literal);
		return literal;
	}

	comment (node, parent) {
		if (!parent.nodes || (node.start < parent.raws.node.start && parent.type !== "root" && parent.parent)) {
			return this.comment(node, parent.parent);
		}
		const text = node.value.match(/^(\s*)((?:\S[\s\S]*?)?)(\s*)$/);
		const comment = postcss.comment({
			text: text[2],
			raws: {
				node,
				left: text[1],
				right: text[3],
				inline: node.type === "CommentLine",
			},
		});

		parent.push(comment);
		return comment;
	}
}
module.exports = objectParser;
