import { COMMENT, DECLARATION, RULESET } from "./Enum.js";
import { abs, append, charat, from, indexof, replace, sizeof, strlen, substr, trim } from "./Utility.js";
import { alloc, caret, char, commenter, dealloc, delimit, escaping, identifier, next, node, peek, prev, token, whitespace } from "./Tokenizer.js";
function compile(e) {
	return dealloc(parse("", null, null, null, [""], e = alloc(e), 0, [0], e));
}
function parse(e, s, c, m, g, _, y, x, E) {
	for (var j = 0, M = 0, N = y, P = 0, F = 0, I = 0, L = 1, R = 1, z = 1, B = 0, V = "", H = g, U = _, W = m, G = V; R;) switch (I = B, B = next()) {
		case 40: if (I != 108 && charat(G, N - 1) == 58) {
			indexof(G += replace(delimit(B), "&", "&\f"), "&\f", abs(j ? x[j - 1] : 0)) != -1 && (z = -1);
			break;
		}
		case 34:
		case 39:
		case 91:
			G += delimit(B);
			break;
		case 9:
		case 10:
		case 13:
		case 32:
			G += whitespace(I);
			break;
		case 92:
			G += escaping(caret() - 1, 7);
			continue;
		case 47:
			switch (peek()) {
				case 42:
				case 47:
					append(comment(commenter(next(), caret()), s, c, E), E), (token(I || 1) == 5 || token(peek() || 1) == 5) && strlen(G) && substr(G, -1, void 0) !== " " && (G += " ");
					break;
				default: G += "/";
			}
			break;
		case 123 * L: x[j++] = strlen(G) * z;
		case 125 * L:
		case 59:
		case 0:
			switch (B) {
				case 0:
				case 125: R = 0;
				case 59 + M:
					z == -1 && (G = replace(G, /\f/g, "")), F > 0 && (strlen(G) - N || L === 0 && I === 47) && append(F > 32 ? declaration(G + ";", m, c, N - 1, E) : declaration(replace(G, " ", "") + ";", m, c, N - 2, E), E);
					break;
				case 59: G += ";";
				default: if (append(W = ruleset(G, s, c, j, M, g, x, V, H = [], U = [], N, _), _), B === 123) if (M === 0) parse(G, s, W, W, H, _, N, x, U);
				else {
					switch (P) {
						case 99: if (charat(G, 3) === 110) break;
						case 108: if (charat(G, 2) === 97) break;
						default: M = 0;
						case 100:
						case 109:
						case 115:
					}
					M ? parse(e, W, W, m && append(ruleset(e, W, W, 0, 0, g, x, V, g, H = [], N, U), U), g, U, N, x, m ? H : U) : parse(G, W, W, W, [""], U, 0, x, U);
				}
			}
			j = M = F = 0, L = z = 1, V = G = "", N = y;
			break;
		case 58: N = 1 + strlen(G), F = I;
		default:
			if (L < 1) {
				if (B == 123) --L;
				else if (B == 125 && L++ == 0 && prev() == 125) continue;
			}
			switch (G += from(B), B * L) {
				case 38:
					z = M > 0 ? 1 : (G += "\f", -1);
					break;
				case 44:
					x[j++] = (strlen(G) - 1) * z, z = 1;
					break;
				case 64:
					peek() === 45 && (G += delimit(next())), P = peek(), M = N = strlen(V = G += identifier(caret())), B++;
					break;
				case 45: I === 45 && strlen(G) == 2 && (L = 0);
			}
	}
	return _;
}
function ruleset(e, s, u, d, f, p, h, _, v, y, b, x) {
	for (var S = f - 1, C = f === 0 ? p : [""], w = sizeof(C), T = 0, D = 0, O = 0; T < d; ++T) for (var k = 0, A = substr(e, S + 1, S = abs(D = h[T])), j = e; k < w; ++k) (j = trim(D > 0 ? C[k] + " " + A : replace(A, /&\f/g, C[k]))) && (v[O++] = j);
	return node(e, s, u, f === 0 ? RULESET : _, v, y, b, x);
}
function comment(s, c, l, u) {
	return node(s, c, l, COMMENT, from(char()), substr(s, 2, -2), 0, u);
}
function declaration(e, c, l, u, d) {
	return node(e, c, l, DECLARATION, substr(e, 0, u), substr(e, u + 1, -1), u, d);
}
export { compile };
