"use strict";var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");_Object$defineProperty(exports, "__esModule", { value: true });exports.LINK_MODE = exports.CLIENT_PORT = void 0;exports.clearProjectRecord = clearProjectRecord;exports.clientRecordPath = void 0;exports.getClientFromRequest = getClientFromRequest;exports.getDebugInfoFromRequest = getDebugInfoFromRequest;exports.getIPv4IPAddress = getIPv4IPAddress;exports.getProjectClients = getProjectClients;exports.getRecordClient = getRecordClient;exports.getRecords = getRecords;exports.ipConvert = ipConvert;exports.mkdirsSync = mkdirsSync;exports.recordClient = recordClient;exports.removeClientBySn = removeClientBySn;var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));



var _os = _interopRequireDefault(require("os"));
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _ipaddr = _interopRequireDefault(require("ipaddr.js"));
var _cliSharedUtils = require("../cli-shared-utils"); /**
 * Copyright (C) 2017, hapjs.org. All rights reserved.
 */const home = require('os').homedir();
const CLIENT_PORT = exports.CLIENT_PORT = 39517;
const clientRecordPath = exports.clientRecordPath = _path.default.join(home, 'quickgame-toolkit-client-records.json');
const LINK_MODE = exports.LINK_MODE = {
  NULL: 0,
  WIFI: 1,
  ADB: 2
};

/**
 * 读取记录文件
 * @param {String} clientRecordPath - 记录文件的地址
 * @returns {Object} - 记录的全部设备信息
 */
function getRecords(clientRecordPath) {
  let recordData = { records: {} };
  try {
    recordData = JSON.parse(_fs.default.readFileSync(clientRecordPath).toString());
  } catch (err) {
    console.error(`读取client.json文件出错: ${err.message}`);
  }
  return recordData;
}

/**
 * 将设备记录写入记录文件
 * @param {String} clientRecordPath - 记录文件的地址
 * @param {Object} recordData - 要写入的全部设备记录
 */
function writeRecords(clientRecordPath, recordData) {
  try {
    _fs.default.writeFileSync(clientRecordPath, (0, _stringify.default)(recordData, null, 2));
  } catch (err) {
    (0, _cliSharedUtils.error)(`### App Server ### writeRecords出错: ${err.message}`);
  }
}

/**
 * 读取一个项目的设备记录
 * @param {Object} recordData - 全部设备信息
 * @returns {Array} - 设备记录
 */
function getProjectClients(recordData) {
  let records = recordData.records;
  records = records instanceof Object ? records : {};
  const clients = records[_cliSharedUtils.projectPath];
  if (clients && clients instanceof Array) {
    return clients;
  }
  return [];
}

/**
 * 保存设备记录
 * @param {String} clientRecordPath - 记录文件的地址
 * @param {String} newClient - 新的设备记录
 * @param {callback} logHook - log信息的钩子，参数为要打印的信息
 */
function recordClient(clientRecordPath, newClient, logHook) {
  try {
    const pathParentDir = _path.default.dirname(clientRecordPath);
    let recordData;
    mkdirsSync(pathParentDir);
    if (_fs.default.existsSync(clientRecordPath)) {
      recordData = getRecords(clientRecordPath);
      let clients = getProjectClients(recordData);
      logHook && logHook(`writeClientLogFile(): before: ${(0, _stringify.default)(recordData.records)}`);
      clients = clients.filter((client) => {
        return client.ip !== newClient.ip || client.port !== newClient.port;
      });
      // 保留最后的4条记录，最多记录5条
      while (clients.length > 4) {
        clients.shift();
      }
      recordData.records[_cliSharedUtils.projectPath] = clients;
    } else {
      recordData = { records: {} };
      recordData.records[_cliSharedUtils.projectPath] = [];
    }
    // 写入文件
    recordData.records[_cliSharedUtils.projectPath].push(newClient);
    writeRecords(clientRecordPath, recordData);
    logHook && logHook(`writeClientLogFile(): after: ${(0, _stringify.default)(recordData.records)}`);
  } catch (err) {
    (0, _cliSharedUtils.error)(`### App Server ### recordClient出错: ${err.message}`);
  }
}

/**
 * 根据设备sn和ip获取设备的记录
 * @param {String} clientRecordPath - 记录文件地址
 * @param {String} sn - 设备序列号
 * @param {String} ip
 * @returns {Object} - 匹配的设备记录
 */
function getRecordClient(clientRecordPath, sn, ip) {
  try {
    if (_fs.default.existsSync(clientRecordPath)) {
      const recordData = getRecords(clientRecordPath);
      const clients = getProjectClients(recordData);
      return clients.find((client) => {
        return client.sn === sn && client.ip === ip && client.port;
      });
    }
  } catch (err) {
    (0, _cliSharedUtils.error)(`### App Server ### getRecordClient出错: ${err.message}`);
  }
}

/**
 * 清除一个项目的设备记录
 * @param {String} clientRecordPath
 */
function clearProjectRecord(clientRecordPath) {
  if (_fs.default.existsSync(clientRecordPath)) {
    const recordData = getRecords(clientRecordPath);

    recordData.records[_cliSharedUtils.projectPath] = [];
    writeRecords(clientRecordPath, recordData);
    console.info('### App Server ### 清空调试设备记录');
  } else {
    console.info('### App Server ### 没有需要清空的调试设备记录');
  }
}

/**
 * 从端口映射记录文件中移除项目的一个设备记录
 * @param {String} clientRecordPath - 记录文件的地址
 * @param {String} sn - 设备序列号
 * @param {callback} logHook - log信息的钩子，参数为要打印的信息
 */
function removeClientBySn(clientRecordPath, sn, logHook) {
  if (_fs.default.existsSync(clientRecordPath)) {
    const recordData = getRecords(clientRecordPath);
    const records = recordData.records;
    const clients = getProjectClients(recordData);
    logHook && logHook(`_removeItemFromClientLogFile(): before: ${(0, _stringify.default)(records)}`);
    records[_cliSharedUtils.projectPath] = clients.filter((it) => {
      return it.sn !== sn;
    });
    writeRecords(clientRecordPath, recordData);
    logHook && logHook(`_removeItemFromClientLogFile(): after: ${(0, _stringify.default)(records)}`);
  }
}

/**
 * 创建任意深度的路径的文件夹
 * @param dirname
 * @returns {boolean}
 */
function mkdirsSync(dirname) {
  if (_fs.default.existsSync(dirname)) {
    return true;
  } else {
    if (mkdirsSync(_path.default.dirname(dirname))) {
      _fs.default.mkdirSync(dirname);
      return true;
    }
  }
}

/**
 * 获取服务器端的IP
 */
function getIPv4IPAddress() {
  const ifaces = _os.default.networkInterfaces();
  let result;

  for (const prop in ifaces) {
    if (Object.prototype.hasOwnProperty.call(ifaces, prop)) {
      const iface = ifaces[prop];

      iface.every((eachAlias) => {
        if (
        eachAlias.family === 'IPv4' &&
        !eachAlias.internal &&
        eachAlias.address !== '127.0.0.1')
        {
          result = eachAlias;
          return false;
        }
        return true;
      });

      if (result !== void 0) {
        break;
      }
    }
  }
  return result && result.address;
}

// ipv6地址转ipv4
function ipConvert(str) {
  if (_ipaddr.default.IPv6.isValid(str)) {
    var addr = _ipaddr.default.IPv6.parse(str);
    if (addr.isIPv4MappedAddress()) {return addr.toIPv4Address().toString();}
  }
  return str;
}

/**
 * 冗余方法，获取客户端的请求信息
 * @param request
 * @returns {{clientIp: (any|*|string), sn, linkMode}}
 */
function getClientFromRequest(request) {
  const clientIp = ipConvert(request.ip);
  const serverIp = getIPv4IPAddress();
  const sn = request.header['device-serial-number'];
  let linkMode = LINK_MODE.NULL;
  if (clientIp === '127.0.0.1') {
    linkMode = LINK_MODE.ADB;
  } else if (clientIp !== '127.0.0.1' && clientIp !== serverIp) {
    linkMode = LINK_MODE.WIFI;
  }
  return { clientIp, sn, linkMode, serverIp };
}

/**
 * 获取请求信息
 * @param request
 * @returns {{sn, linkMode, ws, application, devicePort}}
 */
function getDebugInfoFromRequest(request) {
  const { sn, linkMode, serverIp } = getClientFromRequest(request);
  const { ws, application } = request.body;
  const devicePort = ws.split(':')[1].split('/')[0];
  return { sn, linkMode, ws, application, devicePort, serverIp };
}