/*
 * WebI2C, a web interface for flashing I2C EEPROMS, notably FRU EEPROMs for
 * the HBJ11.
 */

import { FRUParser, HBJ11FRUAssembler } from './fru.js';
import { Status, StatusFromU8, USBI2CClassInterface } from './i2c.js';

/**
 * I2CDevice is an I2C device (eg. EEPROM) on the I2C bus, attached via a
 * Programmer.
 */
class I2CDevice {
  constructor(programmer, addr) {
    this.programmer = programmer;
    this.addr = addr;
    this.dump = "";
  }

  /**
   * Treat this device as an I2C EEPROM (eg. 24C02) and read its content.
   * @param {number} addr - The address in the EEPROM to start reading at.
   * @param {number} length - Count of bytes to read starting at address.
   * @returns {Promise<Uint8Array>} Contents of the EEPROM.
   */
  async readFlash(addr, length) {
    // Always send a non-zero seek, otherwise 24C02 sometimes NACKs?
    await this.programmer.writeI2C(this.addr, new Uint8Array([1]));
    await this.programmer.readI2C(this.addr, 1);
    
    // Chunk up reads into 128 bytes.
    let i = 0;
    const max_chunk_size = 128;
    let flash = new Uint8Array(length);
    while (i < length) {
        await this.programmer.writeI2C(this.addr, new Uint8Array([i]));
        let chunk_size = length - i;
        if (chunk_size > max_chunk_size) {
          chunk_size = max_chunk_size;
        }
        let res = await this.programmer.readI2C(this.addr, chunk_size);
        flash.set(new Uint8Array(res.buffer), i);
        i += chunk_size;
    }
    return flash;
  }

  /**
   * Threat this devices as an I2C EEPROM on a HBJ11 and flash it with a given
   * serial nyumber.
   * @param {string} serial - The serial number of the HJB11 to brand it with.
   * @param {HTMLButtonelement} button - Button used to trigger this action,
   *                                     will be disabled while the flashing is
   *                                     performed.
   */
  async writeHBJ11(serial, button) {
      // Always send a non-zero seek, otherwise 24C02 sometimes NACKs?
      await this.programmer.writeI2C(this.addr, new Uint8Array([1]));
      await this.programmer.readI2C(this.addr, 1);

      let text = button.innerText;
      button.disabled = true;
      button.innerText = "Flashing...";

      let data = new HBJ11FRUAssembler(serial).assemble();

      // Chunk up writes into 16 bytes.
      let chunks = [];
      for (let i = 0; i < data.length; i+= 16) {
          chunks.push([i].concat(Array.from(data.slice(i, i+16))));
      }

      for (const chunk of chunks) {
          await this.programmer.writeI2C(this.addr, new Uint8Array(chunk));
      }

      button.disabled = false;
      button.innerText = text;
  }

  render(div) {
    div.innerHTML = "";
    let deviceName = document.createElement("div");
    deviceName.className = "deviceName";
    deviceName.appendChild(document.createTextNode(`Device 0x${this.addr.toString(16)}`));

    div.appendChild(deviceName);

    let deviceOptions = document.createElement("div");
    deviceOptions.className = "deviceOptions";

    let readButton = document.createElement("button");
    readButton.appendChild(document.createTextNode("Read flash"));
    readButton.onclick = async () => {
        let res = await this.readFlash(this.addr, 256);

        this.dump = "";
        const hex = "0123456789ABCDEF";
        for (let i = 0; i < res.length; i += 16) {
          let block = res.slice(i, Math.min(i+16, res.length));
          let addr = ("0000" + i.toString(16)).slice(-4);
          let codes = Array.from(block.values()).map((code) => {
            return " " + hex[(0xF0 & code) >> 4] + hex[0x0f & code];
          }).join("");
          codes += "   ".repeat(16 - block.length);
          let chars = Array.from(block.values()).map((code) => {
            if (code < 0x20 || code > 0x7e) {
              return ".";
            }
            return String.fromCharCode(code);
          }).join("");
          codes += " ".repeat(16 - block.length);
          this.dump += (addr + " " + codes + " " + chars + "\n");
        }

        let p = new FRUParser(res);
        try {
            p.parse();
            this.dump += "\nFRU EEPROM:\n";
            this.dump += p.stringify();
        } catch(err) {
            this.dump += "\nNot an FRU EEPROM: " + err;
        }

        console.log(this.dump);

        this.render(div);
    };
    deviceOptions.appendChild(readButton);

    let makeButton = document.createElement("button");
    makeButton.appendChild(document.createTextNode("Make HBJ11"));
    makeButton.onclick = async () => {
        await this.writeHBJ11(window.prompt("Enter HBJ11 Serial", "A0000"), makeButton);
    };
    deviceOptions.appendChild(makeButton);

    deviceName.appendChild(deviceOptions);

    if (this.dump.length > 0) {
      let deviceDump = document.createElement("pre");

      deviceDump.className = "deviceDump";
      deviceDump.innerText = this.dump;
      div.appendChild(deviceDump);
    }
  }
}

/**
 * A list of I2CDevices, eg. EEPROMs. Used for DOM rendering.
 */
class I2CDeviceList {
  constructor() {
    this.list = [];
  }

  set(devices) {
    this.list = devices;
  }

  render(div) {
    if (this.list.length === 0) {
      div.innerHTML = "<i>No devices...</i>";
      return;
    }

    for (const device of this.list) {
      let deviceDiv = document.createElement("div");
      deviceDiv.className = "device";
      device.render(deviceDiv);
      div.appendChild(deviceDiv);
    }
  }
}

/**
 * A WebI2C compatible programmer accessed over USB.
 */
class Programmer {
  /**
   * @param {USBDevice} usb - The WebUSB device that backs this programmer.
   */
  constructor(usb) {
    this.usb = usb;
    this.i2c = new USBI2CClassInterface(usb);
    this.devices = new I2CDeviceList();
  }
  /**
   * Get programmer manufacturer name.
   * @returns {string} The name.
   */
  get manufacturerName() {
    return this.usb.manufacturerName;
  }

  /**
   * Get programmer product name.
   * @returns {string} The name.
   */
  get productName() {
    return this.usb.productName;
  }

  /**
   * Get programmer serial number.
   * @returns {string} The name.
   */
  get serialNumber() {
    return this.usb.serialNumber;
  }

  /**
   * Compares two Programmers and checks if they're using the same WebUSB
   * device underneath. This is used for housekeeping of the ProgrammerList.
   */
  equal(other) {
    let one = this.usb;
    let two = other.usb;
    return (one.vendorId == two.vendorId)
        && (one.productId == two.productId)
        && (one.serialNumber == two.serialNumber);
  }

  /**
   * Performs an I2C read on the bus of the programmer and reads the resulting
   * data from the buffer. The readout is performed in chunks over multiple
   * Bulk transfer.
   * @param {number} addr - Address of the I2C device to read from.
   * @param {number} length - Number of bytes to read from I2C (not larger than
   *                          BUFFER_SIZE).
   * @returns {object} Object with status and bufer keys. TODO(q3k): declare type.
   */
  async readI2C(addr, length) {
    await this.i2c.readI2C(addr, length);
    let status = await this.i2c.getStatus();
    if (status !== Status.Ack) {
      return {status: status, buffer: null};
    }
    let buffer = new Uint8Array(length);
    let i = 0;
    while (i < length) {
      let chunkSize = length - i;
      if (chunkSize > this.i2c.PACKET_SIZE) {
        chunkSize = this.i2c.PACKET_SIZE;
      }
      let chunk = await this.readBuffer(i, chunkSize);
      buffer.set(new Uint8Array(chunk.buffer), i);
      i += chunkSize;
    }
    return {status: status, buffer: buffer};
  }

  /**
   * Transfers data to internal buffer of programmers and performs an I2C write
   * with the given data.
   * @param {number} addr - Address of the I2C to write data to.
   * @param {ArrayBuffer} data - Data to write to device.
   */
  async writeI2C(addr, data) {
    let i = 0;
    while (i < data.length) {
      let end = i + this.i2c.PACKET_SIZE;
      if (end > data.length) {
        end = data.length;
      }
      let chunk = data.slice(i, end);
      await this.writeBuffer(i, chunk);
      i = end;
    }
    await this.i2c.writeI2C(addr, data.length);
  }

  /**
   * Performs a scan of the I2C bus for all connected devices and upgrades the
   * internal I2CDeviceList with found I2CDevices.
   * @param {HTMLButtonElement} button - Button that will be disabled when the
   *                                     Scan is performed.
   */
  async scan(button) {
    let text = button.innerText;
    button.innerText = "Scanning...";
    button.disabled = true;

    let present = [];
    for (let i = 0; i < 127; i++) {
      let res = await this.readI2C(i, 1);
      switch (res.status) {
        case Status.Ack:
          present.push(new I2CDevice(this, i));
          break;
        case Status.Nack:
          break;
        default:
          throw new Error(`When scanning ${i}: ${StatusFromU8(res.status)}`);
      }
    }
    this.devices.set(present);

    button.disabled = false;
    button.innerText = text;
  }

  /**
   * Blinks the programmer's LED.
   * @param {HTMLButtonElement} button - Button that will be disabled when the
   *                                     LED blinks.
   */
  async blink(button) {
    let on = true;
    button.disabled = true;
    let text = button.innerText;
    button.innerText = "Blinking...";
    for (let i = 0; i < 20; i++) {
      await this.i2c.setLED(on);
      await new Promise(r => setTimeout(r, 100));
      on = !on;
    }
    button.disabled = false;
    button.innerText = text;
  }

  /**
   * Requests buffer readout from device via ReadBuffer control transfer and
   * then performs a single read via the Bulk IN endpoint.
   * @param {number} addr - Address within the buffer to start read at.
   * @param {number} length - Number of bytes to read (not larger than
   *                          PACKET_SIZE).
   * @returns {ArrayBuffer} Data read from buffer.
   */
  async readBuffer(addr, length) {
    await this.i2c.readBuffer(addr, length);
    let status = await this.i2c.getStatus();
    if (status !== Status.Idle) {
      throw new Error(`When requesting buffer: ${StatusFromU8(res.status)}`);
    }
    let res = await this.i2c.bulkIn(length);
    return res.data;
  }

  /**
   * Writes bytes to internal buffer.
   * @param {number} addr - Address within the buffer to start write at.
   * @param {ArrayBuffer} data - Data to write to buffer (must not be longer
   *                             than PACKET_SIZE).
   */
  async writeBuffer(addr, data) {
    await this.i2c.setWritePointer(addr);
    let status = await this.i2c.getStatus();
    if (status !== Status.Idle) {
      throw new Error(`When setting pointer: ${StatusFromU8(res.status)}`);
    }
    await this.i2c.bulkOut(data);
  }


  render(div) {
    let programmer = document.createElement("div");
    programmer.className = "programmer";
    let programmerName = document.createElement("div");
    programmerName.className = "programmerName";
    programmerName.appendChild(document.createTextNode(this.manufacturerName));
    programmerName.appendChild(document.createTextNode(" "));
    let b = document.createElement("b");
    b.textContent = this.productName;
    programmerName.appendChild(b);

    let programmerOptions = document.createElement("div");
    programmerOptions.className = "programmerOptions";

    let blinkButton = document.createElement("button");
    blinkButton.appendChild(document.createTextNode("Blink LED"));
    blinkButton.onclick = async () => {
        await this.blink(blinkButton);
    };
    programmerOptions.appendChild(blinkButton);

    let devices = document.createElement("div");
    devices.className = "devices";

    let scanButton = document.createElement("button");
    scanButton.appendChild(document.createTextNode("Scan I2C Bus"));
    scanButton.onclick = async () => {
        await this.scan(scanButton);
        devices.innerText = "";
        this.devices.render(devices)
    };
    programmerOptions.appendChild(scanButton);

    programmerName.appendChild(programmerOptions);
    programmer.appendChild(programmerName);

    this.devices.render(devices)
    programmer.append(devices);

    div.appendChild(programmer);
  }
}

/**
 * List of Programmers, used for rendering to DOM.
 */
class ProgrammerList {
  constructor(list) {
    this.list = [];
    for (const l of list) {
      this.list.push(l);
    }
    this.status = {};
  }
  async addProgrammer(programmer) {
    let existing = this.list.filter(d => d.equal(programmer));
    if (existing.length == 0) {
      this.list.push(programmer);
      await programmer.i2c.open();
    }
  }
  removeProgrammer(programmer) {
    this.list = this.list.filter(d => !d.equal(programmer));
  }
  render() {
    let div = document.querySelector("#programmers");
    div.innerText = "";
    for (const programmer of this.list) {
        programmer.render(div);
    }
  }
}

if (navigator.usb === undefined || navigator.usb.requestDevice === undefined) {
    alert("No WebUSB support! Please use a Chromium-based browser.");
}

// 'global' ProgrammerList, modified by document/USB events.
let list = null;

document.addEventListener('DOMContentLoaded', async () => {
    let programmers = (await navigator.usb.getDevices()).map(d => new Programmer(d));
    for (const programmer of programmers) {
      await programmer.i2c.open();
    }
    list = new ProgrammerList(programmers);
    list.render();
});

navigator.usb.addEventListener('connect', async event => {
    await list.addProgrammer(new Programmer(event.device));
    list.render();
});

navigator.usb.addEventListener('disconnect', event => {
    list.removeProgrammer(new Programmer(event.device));
    list.render();
});

document.getElementById("connect").onclick = async () => {
    let device;
    try {
      device = await navigator.usb.requestDevice({
          filters: [{
              vendorId: 0x16c0,
              productId: 0x27d8,
          }]
      });
    } catch (err) {
      return;
    };
    if (device !== undefined) {
      await list.addProgrammer(new Programmer(device));
      list.render();
    }
};
