import { Lexer, Parser, Interpreter, Config, getAssignmentInfo, getReassignmentInfo, isNone, parseColorSpec, parseFunctionSpec } from './chunk-OCQX3WYJ.js';
import './chunk-LZTXD3LN.js';
import { ZodError } from '@tokens-studio/schema-validation';
import * as readlineSync from 'readline-sync';

function isPlainObject(v) {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}
function summarizeZodError(err) {
  return err.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; ");
}
function parseTokenScriptSchemaResponse(data) {
  if (!isPlainObject(data)) {
    throw new Error("Invalid schema structure: expected an object");
  }
  const requireString = (key) => {
    const value = data[key];
    if (typeof value !== "string") {
      throw new Error(`Invalid schema structure: missing or non-string field "${key}"`);
    }
    return value;
  };
  const id = requireString("id");
  const type = requireString("type");
  const schema = requireString("schema");
  const slug = requireString("slug");
  const version = requireString("version");
  if (!("content" in data)) {
    throw new Error('Invalid schema structure: missing field "content"');
  }
  const rawContent = data.content;
  if (!isPlainObject(rawContent)) {
    throw new Error('Invalid schema structure: "content" must be an object');
  }
  const contentType = rawContent.type;
  let content;
  try {
    if (contentType === "color") {
      content = parseColorSpec(rawContent);
    } else if (contentType === "function") {
      content = parseFunctionSpec(rawContent);
    } else {
      throw new Error(
        `Unsupported content.type "${String(contentType)}" \u2014 expected "color" or "function"`
      );
    }
  } catch (err) {
    const detail = err instanceof ZodError ? summarizeZodError(err) : err instanceof Error ? err.message : String(err);
    throw new Error(`Invalid schema structure: content: ${detail}`);
  }
  let license_name;
  if ("license_name" in data) {
    const raw = data.license_name;
    if (raw !== null && raw !== void 0 && typeof raw !== "string") {
      throw new Error('Invalid schema structure: "license_name" must be a string or null');
    }
    license_name = raw;
  }
  return { id, type, schema, slug, version, content, license_name };
}
async function fetchTokenScriptSchema(schemaUri, options = {}) {
  const { timeout = 1e4, headers = {}, signal } = options;
  const controller = signal ? new AbortController() : new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);
  if (signal) {
    signal.addEventListener("abort", () => controller.abort());
  }
  try {
    const response = await fetch(schemaUri, {
      signal: controller.signal,
      headers: {
        Accept: "application/json",
        "User-Agent": "TokenScript-Interpreter/1.0",
        ...headers
      }
    });
    clearTimeout(timeoutId);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
    }
    const data = await response.json();
    return parseTokenScriptSchemaResponse(data);
  } catch (error) {
    clearTimeout(timeoutId);
    if (error instanceof Error) {
      if (error.name === "AbortError") {
        throw new Error(`Schema fetch timeout after ${timeout}ms`);
      }
      if (error.message.startsWith("Invalid schema structure") || error.message.startsWith("HTTP error")) {
        throw error;
      }
      throw new Error(`Failed to fetch schema: ${error.message}`);
    }
    throw new Error("Unknown error occurred while fetching schema");
  }
}
async function fetchAndRegisterSchemas(schemaUris, config) {
  const configInstance = config || new Config();
  if (!schemaUris || schemaUris.length === 0) {
    return configInstance;
  }
  const schemas = await Promise.all(
    schemaUris.map(async (uri) => {
      const schemaResponse = await fetchTokenScriptSchema(uri);
      return {
        uri,
        schema: schemaResponse.content
      };
    })
  );
  return configInstance.registerSchemas(schemas);
}
async function startRepl(options = {}) {
  const { mode = "inline", schemas, references: initialReferences } = options;
  const config = await fetchAndRegisterSchemas(schemas ?? []);
  const references = { ...initialReferences };
  let scriptLines = [];
  console.log(
    `Mode: ${mode === "inline" ? "inline (execute each line)" : "script (accumulate and execute)"}`
  );
  console.log('"exit()" to exit, "clear()" to clear.');
  console.log("");
  while (true) {
    try {
      const input = readlineSync.question("> ");
      const cmd = input.toLowerCase().trim();
      if (cmd === "exit()") {
        break;
      }
      if (cmd === "clear()") {
        scriptLines = [];
        console.clear();
        console.log(
          `Mode: ${mode === "inline" ? "inline (execute each line)" : "script (accumulate and execute)"}`
        );
        console.log('"exit()" to exit, "clear()" to clear.');
        console.log("");
        continue;
      }
      if (input.trim() === "") {
        continue;
      }
      let result;
      if (mode === "inline") {
        result = interpretExpression(input, references, config, true);
      } else {
        const autoSemiLastLineInput = input.endsWith(";") ? input : `${input};`;
        scriptLines.push(autoSemiLastLineInput);
        const fullScript = scriptLines.join("\n");
        result = interpretExpression(fullScript, references, config, false);
      }
      if (result) {
        console.log(result);
      }
    } catch (error) {
      console.error(`Error: ${error.message}`);
      if (mode === "script") {
        scriptLines.pop();
      }
    }
  }
}
function getDisplayValue(ast, interpreter, result) {
  const assignmentInfo = getAssignmentInfo(ast);
  const reassignmentInfo = getReassignmentInfo(ast);
  if (assignmentInfo) {
    if (assignmentInfo.hasAssignment) {
      const varValue = interpreter.getSymbol(assignmentInfo.varName);
      if (varValue) {
        return varValue.toString();
      }
    }
    return;
  }
  if (reassignmentInfo) {
    const varValue = interpreter.getSymbol(reassignmentInfo.varName);
    if (varValue) {
      return varValue.toString();
    }
    return;
  }
  if (isNone(result)) {
    return;
  }
  if (typeof result === "string") {
    return result;
  }
  return result.toString();
}
function interpretExpression(code, references, config, isInline) {
  try {
    const lexer = new Lexer(code);
    const parser = new Parser(lexer);
    const ast = parser.parse(isInline);
    if (!ast) {
      return "No result (empty input)";
    }
    const interpreter = new Interpreter(ast, { references, config });
    const result = interpreter.interpret();
    return getDisplayValue(ast, interpreter, result);
  } catch (error) {
    throw new Error(`Interpretation failed: ${error.message}`);
  }
}

export { interpretExpression, startRepl };
//# sourceMappingURL=repl.js.map
//# sourceMappingURL=repl.js.map