'use strict';

const childProcess = require('child_process');
const Readline = require('@serialport/parser-readline');

// get only serial port names
function checkPathOfDevice(path) {
  return (/(tty(S|ACM|USB|AMA|MFD|O)|rfcomm)/).test(path) && path;
}

function propName(name) {
  return {
    'DEVNAME': 'comName',
    'ID_VENDOR_ENC': 'manufacturer',
    'ID_SERIAL_SHORT': 'serialNumber',
    'ID_VENDOR_ID': 'vendorId',
    'ID_MODEL_ID': 'productId',
    'DEVLINKS': 'pnpId'
  }[name.toUpperCase()];
}

function decodeHexEscape(str) {
  return str.replace(/\\x([a-fA-F0-9]{2})/g, (a, b) => {
    return String.fromCharCode(parseInt(b, 16));
  });
}

function propVal(name, val) {
  if (name === 'pnpId') {
    const match = val.match(/\/by-id\/([^\s]+)/);
    return (match && match[1]) || undefined;
  }
  if (name === 'manufacturer') {
    return decodeHexEscape(val);
  }
  if (/^0x/.test(val)) {
    return val.substr(2);
  }
  return val;
}

function listLinux() {
  return new Promise((resolve, reject) => {
    const ports = [];
    const ude = childProcess.spawn('udevadm', ['info', '-e']);
    const lines = ude.stdout.pipe(new Readline());
    ude.on('error', reject);
    lines.on('error', reject);

    let port = {};
    let skipPort = false;
    lines.on('data', (line) => {
      const lineType = line.slice(0, 1);
      const data = line.slice(3);
      // new port entry
      if (lineType === 'P') {
        port = {
          manufacturer: undefined,
          serialNumber: undefined,
          pnpId: undefined,
          locationId: undefined,
          vendorId: undefined,
          productId: undefined
        };
        skipPort = false;
        return;
      }

      if (skipPort) { return }

      // Check dev name and save port if it matches flag to skip the rest of the data if not
      if (lineType === 'N') {
        if (checkPathOfDevice(data)) {
          ports.push(port);
        } else {
          skipPort = true;
        }
        return;
      }

      // parse data about each port
      if (lineType === 'E') {
        const keyValue = data.match(/^(.+)=(.*)/);
        if (!keyValue) { return }
        const key = propName(keyValue[1]);
        if (!key) { return }
        port[key] = propVal(key, keyValue[2]);
      }
    });

    lines.on('finish', () => resolve(ports));
  });
}

module.exports = listLinux;
