import { writeString, writeStringChunked } from './connection.js';

export async function enterRawRepl() {
  await writeString('\x03\x03');
  await sleep(100);
  await writeString('\x01');
  await sleep(100);
}

export async function executeCode(code, options = {}) {
  const { onProgress } = options;
  await enterRawRepl();
  await writeStringChunked(code, 32, 25, onProgress || null);
  await writeString('\x04');
}

export async function stopExecution() {
  await writeString('\x03\x03');
}

export async function saveToDevice(code, filename = 'main.py', options = {}) {
  const script = [
    `f = open('${filename}', 'w')`,
    `f.write(${JSON.stringify(code)})`,
    `f.close()`,
    `print('Saved to ${filename}')`,
  ].join('\n');
  await executeCode(script, options);
}

export async function writeFileToDevice(content, filename) {
  // Escape the content properly for Python string - handle newlines, quotes, backslashes
  const escaped = content
    .replace(/\\/g, '\\\\')
    .replace(/'/g, "\\'")
    .replace(/\n/g, '\\n')
    .replace(/\r/g, '\\r');
  
  const script = [
    `f = open('${filename}', 'w')`,
    `f.write('${escaped}')`,
    `f.close()`,
    `print('Saved ${filename}')`,
  ].join('\n');
  await executeCode(script);
}

export async function readFileFromDevice(filename, onOutput) {
  // Read file and print with markers so we can extract content
  const startMarker = `__WS_START_${Date.now()}__`;
  const endMarker = `__WS_END_${Date.now()}__`;
  
  const script = [
    `try:`,
    `  f = open('${filename}', 'r')`,
    `  data = f.read()`,
    `  f.close()`,
    `  print('${startMarker}')`,
    `  print(data, end='')`,
    `  print('${endMarker}')`,
    `except Exception as e:`,
    `  print('Error: ' + str(e))`,
  ].join('\n');
  
  // Set up a listener to capture output between markers
  let captured = '';
  let capturing = false;
  
  const listener = (text) => {
    if (!onOutput) return;
    
    const startIdx = text.indexOf(startMarker);
    const endIdx = text.indexOf(endMarker);
    
    if (startIdx !== -1) {
      capturing = true;
      captured = text.substring(startIdx + startMarker.length);
    }
    
    if (capturing) {
      if (endIdx !== -1) {
        captured += text.substring(0, endIdx);
        capturing = false;
        onOutput(captured);
      } else {
        captured += text;
      }
    }
  };
  
  // This will be handled by the caller setting up the listener
  // For now, just execute and let caller handle output
  await executeCode(script);
  
  return { startMarker, endMarker };
}

function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}
