var emulator, zoom = 1, cdrom={url: "basekernel.iso"}, serialLine="",
    debugMode = false

function loadCDROM(url) {
  if (typeof process == 'object' && process.__nwjs) {
    try {
      var fs = require('fs')
      cdrom = { _url:url, 
                 buffer: Uint8Array.from(fs.readFileSync((process.env.PWD||process.env.HOME||process.env.CWD)+'/'+url)).buffer }
    } catch (e) {
      alert(e.toString())
    }
  }
}
loadCDROM(cdrom.url)

function createEmulator() {
  emulator = new V86({
    wasm_path        : "v86.wasm",
    memory_size      : 64 * 1024 * 1024,  // 64 MB memory ought to be enough for anyone
    vga_memory_size  : 2 * 1024 * 1024,
    screen_container : screen_container,
    bios             : {url: "seabios.bin"},
    vga_bios         : {url: "vgabios.bin"},
    cdrom            : cdrom,
    hda              : {
      buffer: new Uint8Array(16*1024*1024).buffer
    },
    boot_order       : 0x123,
    autostart        : true,
    // log_level        : 0x004000,
  })
  emulator.serial1_send=function(a){for(var b=0;b<a.length;b++) emulator.bus.send("serial1-input",a.charCodeAt(b))};
}
createEmulator()

emulator.add_listener("serial0-output-byte", function(byte) {
  var char = String.fromCharCode(byte);
  // console.log('serial0-output-byte',char,byte,serialLine);
  if(char === "\n")
  {
    console.log(serialLine)
    terminal0Queue.push(serialLine);
    serialLine=""
    return;
  } else
    serialLine += char
})
$('#debugger').terminal(function(command) {
  var tokens = command.split(' ')
  switch (tokens[0]) {
    case 'help':
      this.echo([
        'debug #on',
        'dumpidt',
        'dumpregs',
        'dumpstate',
        'reboot',
        'restart',
        'run',
        'stop',
        'zoom #scale'
      ].join('\n'))
      break;
    case 'debug':
      debugMode=tokens[1]=='0'?false:true
      break;
    case 'dumpregs':
      this.echo(emulator.v86.cpu.debug.get_regs_short()[0].split(' ').filter(x => x).join('\n'))
      break;
    case 'dumpidt':
      var _debug = debugMode
      debugMode=1
      this.echo(emulator.v86.cpu.debug.dump_idt())
      debugMode=_debug
      break;
    case 'dumpstate':
      this.echo(emulator.v86.cpu.debug.get_state().split(' ').filter(x => (x&&x.length>2)).join('\n'))
      break;
    case 'reboot':
      loadCDROM(cdrom.url||cdrom._url);
      emulator.destroy();
      createEmulator();
      break;
    case 'restart':
      emulator.restart()
      break;
    case 'run':
      this.echo("Resumed VM. Use stop to suspend VM.")
      emulator.run()
      break;
    case 'stop':
      emulator.stop()
      this.echo("Stopped VM. Use run to resume")
      break;
    case 'zoom':
      zoom=Number(tokens[1]||1)
      resizeAll()
      break;
  }
}, { 
    greetings: '### VM86 Debugger ###',
    height:280
}); 
$('#terminal').terminal(function(command) {
  emulator.serial0_send(command+'\n');
}, { 
    greetings: '### Serial Console ###',
    height:280
});
var terminal0 = $('#terminal').terminal(),
    terminal0Queue = []
$('#terminal').terminal().echo("Ready.")
// get the debug output the hard way
consoleCallback=function (message) {
  // terminal0.echo(message)
  if (debugMode && message!=undefined) terminal0Queue.push(message)
}
setInterval(function () {
  if (terminal0Queue.length) {
    terminal0.echo(terminal0Queue.join('\n'))
    terminal0Queue=[]
  }
},200);

function resizeAll() {
  var vmcell = $('#vmcell'),
      vmcanv = $('canvas'),
      win    = $(window)
 // console.log(vmcell.width(),vmcanv.width(),vmcanv.height())
 if (vmcanv.height()>100) {
   vmcell.css('max-width',(vmcanv.width()*zoom+30)+'px')
   vmcell.css('width',(vmcanv.width()*zoom+30)+'px')
   vmcell.css('height',(Math.floor(vmcanv.height()*zoom*1.1+30)+'px'))
 }
 vmcanv[0].style='display:block;transform:scale('+zoom+','+(zoom*1.1)+');'
}

setInterval(resizeAll,1000)
$("#terminal").on('click', function() {
  $("#terminal").css("border","2px solid white");
  $("#debugger").css("border","1px solid white");
  $("#vmcell").css("border","1px solid white");
});
$("#debugger").on('click', function() {
  $("#debugger").css("border","2px solid white");
  $("#terminal").css("border","1px solid white");
  $("#vmcell").css("border","1px solid white");
});
$("canvas").on('click', function() {
  $("#debugger").css("border","1px solid white");
  $("#terminal").css("border","1px solid white");
  $("#vmcell").css("border","2px solid white");
});
$("#vmcell").css("border","2px solid white");