text: "use strict";
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = Object.setPrototypeOf ||
          ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
          function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
      return function (d, b) {
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  Object.defineProperty(exports, "__esModule", { value: true });
  var HF2 = pxt.HF2;
  var U = pxt.U;
  var HID = undefined;
  function getHID() {
      if (HID === undefined) {
          try {
              HID = require("node-hid");
          }
          catch (e) {
              pxt.log('node-hid failed to load, ignoring...');
              HID = null;
          }
      }
      return HID;
  }
  function listAsync() {
      for (var _i = 0, _a = getHF2Devices(); _i < _a.length; _i++) {
          var h = _a[_i];
          console.log(deviceInfo(h));
      }
      return Promise.resolve();
  }
  exports.listAsync = listAsync;
  function serialAsync() {
      return initAsync()
          .then(function (d) {
          d.autoReconnect = true;
          connectSerial(d);
      });
  }
  exports.serialAsync = serialAsync;
  function dmesgAsync() {
      return initAsync()
          .then(function (d) { return d.talkAsync(pxt.HF2.HF2_CMD_DMESG)
          .then(function (resp) {
          console.log(U.fromUTF8(U.uint8ArrayToString(resp)));
          return d.disconnectAsync();
      }); });
  }
  exports.dmesgAsync = dmesgAsync;
  function hex(n) {
      return ("000" + n.toString(16)).slice(-4);
  }
  function deviceInfo(h) {
      return h.product + " (by " + h.manufacturer + " at USB " + hex(h.vendorId) + ":" + hex(h.productId) + ")";
  }
  exports.deviceInfo = deviceInfo;
  function getHF2Devices() {
      var hid = getHID();
      if (!hid)
          return [];
      var devices = hid.devices();
      for (var _i = 0, devices_1 = devices; _i < devices_1.length; _i++) {
          var d = devices_1[_i];
          pxt.debug(JSON.stringify(d));
      }
      var serial = pxt.appTarget.serial;
      return devices.filter(function (d) {
          return (serial && parseInt(serial.productId) == d.productId && parseInt(serial.vendorId) == d.vendorId) ||
              (d.release & 0xff00) == 0x4200;
      });
  }
  exports.getHF2Devices = getHF2Devices;
  function hf2ConnectAsync(path, raw) {
      if (raw === void 0) { raw = false; }
      return Promise.resolve()
          .then(function () {
          // in .then() to make sure we catch errors
          var h = new HF2.Wrapper(new HidIO(path));
          h.rawMode = raw;
          return h.reconnectAsync(true).then(function () { return h; });
      });
  }
  exports.hf2ConnectAsync = hf2ConnectAsync;
  function mkPacketIOAsync() {
      return Promise.resolve()
          .then(function () {
          // in .then() to make sure we catch errors
          return new HidIO(null);
      });
  }
  exports.mkPacketIOAsync = mkPacketIOAsync;
  pxt.HF2.mkPacketIOAsync = mkPacketIOAsync;
  var hf2Dev;
  function initAsync(path) {
      if (path === void 0) { path = null; }
      if (!hf2Dev) {
          hf2Dev = hf2ConnectAsync(path);
      }
      return hf2Dev;
  }
  exports.initAsync = initAsync;
  function connectSerial(w) {
      process.stdin.on("data", function (buf) {
          w.sendSerialAsync(new Uint8Array(buf)).done();
      });
      w.onSerial = function (arr, iserr) {
          var buf = new Buffer(arr);
          if (iserr)
              process.stderr.write(buf);
          else
              process.stdout.write(buf);
      };
  }
  exports.connectSerial = connectSerial;
  var HIDError = /** @class */ (function (_super) {
      __extends(HIDError, _super);
      function HIDError(m) {
          var _this = _super.call(this, m) || this;
          _this.message = m;
          return _this;
      }
      return HIDError;
  }(Error));
  exports.HIDError = HIDError;
  var HidIO = /** @class */ (function () {
      function HidIO(requestedPath) {
          this.requestedPath = requestedPath;
          this.onData = function (v) { };
          this.onEvent = function (v) { };
          this.onError = function (e) { };
          this.connect();
      }
      HidIO.prototype.connect = function () {
          var _this = this;
          var hid = getHID();
          U.assert(hid);
          if (this.requestedPath == null) {
              var devs = getHF2Devices();
              if (devs.length == 0)
                  throw new HIDError("no devices found");
              this.path = devs[0].path;
          }
          else {
              this.path = this.requestedPath;
          }
          this.dev = new HID.HID(this.path);
          this.dev.on("data", function (v) {
              //console.log("got", v.toString("hex"))
              _this.onData(new Uint8Array(v));
          });
          this.dev.on("error", function (v) { return _this.onError(v); });
      };
      HidIO.prototype.sendPacketAsync = function (pkt) {
          var _this = this;
          //console.log("SEND: " + new Buffer(pkt).toString("hex"))
          return Promise.resolve()
              .then(function () {
              var lst = [0];
              for (var i = 0; i < Math.max(64, pkt.length); ++i)
                  lst.push(pkt[i] || 0);
              _this.dev.write(lst);
          });
      };
      HidIO.prototype.error = function (msg) {
          var fullmsg = "HID error on " + this.path + ": " + msg;
          console.error(fullmsg);
          throw new HIDError(fullmsg);
      };
      HidIO.prototype.disconnectAsync = function () {
          var _this = this;
          if (!this.dev)
              return Promise.resolve();
          // see https://github.com/node-hid/node-hid/issues/61
          this.dev.removeAllListeners("data");
          this.dev.removeAllListeners("error");
          var pkt = new Uint8Array([0x48]);
          this.sendPacketAsync(pkt).catch(function (e) { });
          return Promise.delay(100)
              .then(function () {
              if (_this.dev) {
                  _this.dev.close();
                  _this.dev = null;
              }
          });
      };
      HidIO.prototype.reconnectAsync = function () {
          var _this = this;
          return this.disconnectAsync()
              .then(function () {
              _this.connect();
          });
      };
      return HidIO;
  }());
  exports.HidIO = HidIO;
  