/* handshake flags */
const NBD_FLAG_FIXED_NEWSTYLE = 0x1;
const NBD_FLAG_NO_ZEROES = 0x2;

/* transmission flags */
const NBD_FLAG_HAS_FLAGS = 0x1;
const NBD_FLAG_READ_ONLY = 0x2;

/* option negotiation */
const NBD_OPT_EXPORT_NAME = 0x1;
const NBD_REP_FLAG_ERROR = 0x1 << 31;
const NBD_REP_ERR_UNSUP = NBD_REP_FLAG_ERROR | 1;

/* command definitions */
const NBD_CMD_READ = 0;
const NBD_CMD_WRITE = 1;
const NBD_CMD_DISC = 2;
const NBD_CMD_TRIM = 4;

/* errno */
const EPERM = 1;
const EIO = 5;
const EINVAL = 22;
const ENOSPC = 28;

/* internal object state */
const NBD_STATE_UNKNOWN = 1;
const NBD_STATE_OPEN = 2;
const NBD_STATE_WAIT_CFLAGS = 3;
const NBD_STATE_WAIT_OPTION = 4;
const NBD_STATE_TRANSMISSION = 5;

export default class NBDServer {
  constructor(endpoint, file, id, token) {
    this.socketStarted = () => {};
    this.socketClosed = () => {};
    this.errorReadingFile = () => {};
    this.file = file;
    this.id = id;
    this.endpoint = endpoint;
    this.ws = null;
    this.state = NBD_STATE_UNKNOWN;
    this.msgbuf = null;
    this.start = function() {
      this.ws = new WebSocket(this.endpoint, [token]);
      this.state = NBD_STATE_OPEN;
      this.ws.binaryType = 'arraybuffer';
      this.ws.onmessage = this._on_ws_message.bind(this);
      this.ws.onopen = this._on_ws_open.bind(this);
      this.ws.onclose = this._on_ws_close.bind(this);
      this.ws.onerror = this._on_ws_error.bind(this);
      this.socketStarted();
    };
    this.stop = function() {
      if (this.ws.readyState == 1) {
        this.ws.close();
        this.state = NBD_STATE_UNKNOWN;
      }
    };
    this._on_ws_error = function(ev) {
      console.log(`${endpoint} error: ${ev.error}`);
      console.log(JSON.stringify(ev));
    };
    this._on_ws_close = function(ev) {
      console.log(
        `${endpoint} closed with code: ${ev.code} + reason: ${ev.reason}`
      );
      console.log(JSON.stringify(ev));
      this.socketClosed(ev.code);
    };
    /* websocket event handlers */
    this._on_ws_open = function() {
      console.log(endpoint + ' opened');
      this.client = {
        flags: 0
      };
      this._negotiate();
    };
    this._on_ws_message = function(ev) {
      var data = ev.data;
      if (this.msgbuf == null) {
        this.msgbuf = data;
      } else {
        const tmp = new Uint8Array(this.msgbuf.byteLength + data.byteLength);
        tmp.set(new Uint8Array(this.msgbuf), 0);
        tmp.set(new Uint8Array(data), this.msgbuf.byteLength);
        this.msgbuf = tmp.buffer;
      }
      for (;;) {
        var handler = this.recv_handlers[this.state];
        if (!handler) {
          console.log('no handler for state ' + this.state);
          this.stop();
          break;
        }
        var consumed = handler(this.msgbuf);
        if (consumed < 0) {
          console.log(
            'handler[state=' + this.state + '] returned error ' + consumed
          );
          this.stop();
          break;
        }
        if (consumed == 0) {
          break;
        }
        if (consumed > 0) {
          if (consumed == this.msgbuf.byteLength) {
            this.msgbuf = null;
            break;
          }
          this.msgbuf = this.msgbuf.slice(consumed);
        }
      }
    };
    this._negotiate = function() {
      var buf = new ArrayBuffer(18);
      var data = new DataView(buf, 0, 18);
      /* NBD magic: NBDMAGIC */
      data.setUint32(0, 0x4e42444d);
      data.setUint32(4, 0x41474943);
      /* newstyle negotiation: IHAVEOPT */
      data.setUint32(8, 0x49484156);
      data.setUint32(12, 0x454f5054);
      /* flags: fixed newstyle negotiation, no padding */
      data.setUint16(16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES);
      this.state = NBD_STATE_WAIT_CFLAGS;
      this.ws.send(buf);
    };
    /* handlers */
    this._handle_cflags = function(buf) {
      if (buf.byteLength < 4) {
        return 0;
      }
      var data = new DataView(buf, 0, 4);
      this.client.flags = data.getUint32(0);
      this.state = NBD_STATE_WAIT_OPTION;
      return 4;
    };
    this._handle_option = function(buf) {
      if (buf.byteLength < 16) return 0;
      var data = new DataView(buf, 0, 16);
      if (data.getUint32(0) != 0x49484156 || data.getUint32(4) != 0x454f5054) {
        console.log('invalid option magic');
        return -1;
      }
      var opt = data.getUint32(8);
      var len = data.getUint32(12);
      if (buf.byteLength < 16 + len) {
        return 0;
      }
      switch (opt) {
        case NBD_OPT_EXPORT_NAME:
          var n = 10;
          if (!(this.client.flags & NBD_FLAG_NO_ZEROES)) n += 124;
          var resp = new ArrayBuffer(n);
          var view = new DataView(resp, 0, 10);
          /* export size. */
          var size = this.file.size;
          // eslint-disable-next-line prettier/prettier
          view.setUint32(0, Math.floor(size / (2 ** 32)));
          view.setUint32(4, size & 0xffffffff);
          /* transmission flags: read-only */
          view.setUint16(8, NBD_FLAG_HAS_FLAGS | NBD_FLAG_READ_ONLY);
          this.ws.send(resp);
          this.state = NBD_STATE_TRANSMISSION;
          break;
        default:
          console.log('handle_option: Unsupported option: ' + opt);
          /* reject other options */
          var resp1 = new ArrayBuffer(20);
          var view1 = new DataView(resp1, 0, 20);
          view1.setUint32(0, 0x0003e889);
          view1.setUint32(4, 0x045565a9);
          view1.setUint32(8, opt);
          view1.setUint32(12, NBD_REP_ERR_UNSUP);
          view1.setUint32(16, 0);
          this.ws.send(resp1);
      }
      return 16 + len;
    };
    this._create_cmd_response = function(req, rc, data = null) {
      var len = 16;
      if (data) len += data.byteLength;
      var resp = new ArrayBuffer(len);
      var view = new DataView(resp, 0, 16);
      view.setUint32(0, 0x67446698);
      view.setUint32(4, rc);
      view.setUint32(8, req.handle_msB);
      view.setUint32(12, req.handle_lsB);
      if (data) new Uint8Array(resp, 16).set(new Uint8Array(data));
      return resp;
    };
    this._handle_cmd = function(buf) {
      if (buf.byteLength < 28) {
        return 0;
      }
      var view = new DataView(buf, 0, 28);
      if (view.getUint32(0) != 0x25609513) {
        console.log('invalid request magic');
        return -1;
      }
      var req = {
        flags: view.getUint16(4),
        type: view.getUint16(6),
        handle_msB: view.getUint32(8),
        handle_lsB: view.getUint32(12),
        offset_msB: view.getUint32(16),
        offset_lsB: view.getUint32(20),
        length: view.getUint32(24)
      };
      /* we don't support writes, so nothing needs the data at present */
      /* req.data = buf.slice(28); */
      var err = 0;
      var consumed = 28;
      /* the command handlers return 0 on success, and send their
       * own response. Otherwise, a non-zero error code will be
       * used as a simple error response
       */
      switch (req.type) {
        case NBD_CMD_READ:
          err = this._handle_cmd_read(req);
          break;
        case NBD_CMD_DISC:
          err = this._handle_cmd_disconnect(req);
          break;
        case NBD_CMD_WRITE:
          /* we also need length bytes of data to consume a write
           * request */
          if (buf.byteLength < 28 + req.length) {
            return 0;
          }
          consumed += req.length;
          err = EPERM;
          break;
        case NBD_CMD_TRIM:
          err = EPERM;
          break;
        default:
          console.log('invalid command 0x' + req.type.toString(16));
          err = EINVAL;
      }
      if (err) {
        console.log('error handle_cmd: ' + err);
        var resp = this._create_cmd_response(req, err);
        this.ws.send(resp);
        if (err == ENOSPC) {
          this.errorReadingFile();
          this.stop();
        }
      }
      return consumed;
    };
    this._handle_cmd_read = function(req) {
      var offset;
      // eslint-disable-next-line prettier/prettier
      offset = (req.offset_msB * 2 ** 32) + req.offset_lsB;
      if (offset > Number.MAX_SAFE_INTEGER) return ENOSPC;
      if (offset + req.length > Number.MAX_SAFE_INTEGER) return ENOSPC;
      if (offset + req.length > file.size) return ENOSPC;
      var blob = this.file.slice(offset, offset + req.length);
      var reader = new FileReader();

      reader.onload = function(ev) {
        var reader = ev.target;
        if (reader.readyState != FileReader.DONE) return;
        var resp = this._create_cmd_response(req, 0, reader.result);
        this.ws.send(resp);
      }.bind(this);

      reader.onerror = function(ev) {
        var reader = ev.target;
        console.log('error reading file: ' + reader.error);
        var resp = this._create_cmd_response(req, EIO);
        this.ws.send(resp);
      }.bind(this);
      reader.readAsArrayBuffer(blob);
      return 0;
    };
    this._handle_cmd_disconnect = function() {
      this.stop();
      return 0;
    };
    this.recv_handlers = Object.freeze({
      [NBD_STATE_WAIT_CFLAGS]: this._handle_cflags.bind(this),
      [NBD_STATE_WAIT_OPTION]: this._handle_option.bind(this),
      [NBD_STATE_TRANSMISSION]: this._handle_cmd.bind(this)
    });
  }
}
