text: import axios from 'axios';
  import { fs } from 'appium-support';
  import logger from './logger';
  import _ from 'lodash';
  
  
  const hubUri = (config) => {
    const protocol = config.hubProtocol || 'http';
    return `${protocol}://${config.hubHost}:${config.hubPort}`;
  };
  
  async function registerNode (configFile, addr, port) {
    let data;
    try {
      data = await fs.readFile(configFile, 'utf-8');
    } catch (err) {
      logger.error(`Unable to load node configuration file to register with grid: ${err.message}`);
      return;
    }
  
    // Check presence of data before posting  it to the selenium grid
    if (!data) {
      logger.error('No data found in the node configuration file to send to the grid');
      return;
    }
    postRequest(data, addr, port);
  }
  
  async function registerToGrid (postOptions, configHolder) {
    try {
      const {status} = await axios(postOptions);
      if (status !== 200) {
        throw new Error(`Request failed with code ${status}`);
      }
      logger.debug(`Appium successfully registered with the the grid on ` +
        hubUri(configHolder.configuration));
    } catch (err) {
      logger.error(`An attempt to register with the grid was unsuccessful: ${err.message}`);
    }
  }
  
  function postRequest (data, addr, port) {
    // parse json to get hub host and port
    let configHolder;
    try {
      configHolder = JSON.parse(data);
    } catch (err) {
      logger.errorAndThrow(`Syntax error in node configuration file: ${err.message}`);
    }
  
    // Move Selenium 3 configuration properties to configuration object
    if (!_.has(configHolder, 'configuration')) {
      let configuration = {};
      for (const property in configHolder) {
        if (_.has(configHolder, property) && property !== 'capabilities') {
          configuration[property] = configHolder[property];
          delete configHolder[property];
        }
      }
      configHolder.configuration = configuration;
    }
  
    // if the node config does not have the appium/webdriver url, host, and port,
    // automatically add it based on how appium was initialized
    // otherwise, we will take whatever the user setup
    // because we will always set localhost/127.0.0.1. this won't work if your
    // node and grid aren't in the same place
    if (!configHolder.configuration.url || !configHolder.configuration.host || !configHolder.configuration.port) {
      configHolder.configuration.url = `http://${addr}:${port}/wd/hub`;
      configHolder.configuration.host = addr;
      configHolder.configuration.port = port;
    }
    // if the node config does not have id automatically add it
    if (!configHolder.configuration.id) {
      configHolder.configuration.id = `http://${configHolder.configuration.host}:${configHolder.configuration.port}`;
    }
  
    // the post options
    const regRequest = {
      url: `${hubUri(configHolder.configuration)}/grid/register`,
      method: 'POST',
      data: configHolder,
    };
  
    if (configHolder.configuration.register !== true) {
      logger.debug(`No registration sent (${configHolder.configuration.register} = false)`);
      return;
    }
  
    const registerCycleInterval = configHolder.configuration.registerCycle;
    if (isNaN(registerCycleInterval) || registerCycleInterval <= 0) {
      logger.warn(`'registerCycle' is not a valid positive number. ` +
        `No registration request will be sent to the grid.`);
      return;
    }
    // initiate a new Thread
    let first = true;
    logger.debug(`Starting auto register thread for the grid. ` +
      `Will try to register every ${registerCycleInterval} ms.`);
    setInterval(async function registerRetry () {
      if (first) {
        first = false;
        await registerToGrid(regRequest, configHolder);
      } else if (!await isAlreadyRegistered(configHolder)) {
        // make the http POST to the grid for registration
        await registerToGrid(regRequest, configHolder);
      }
    }, registerCycleInterval);
  }
  
  async function isAlreadyRegistered (configHolder) {
    //check if node is already registered
    const id = configHolder.configuration.id;
    try {
      const {data, status} = await axios({
        url: `${hubUri(configHolder.configuration)}/grid/api/proxy?id=${id}`,
        timeout: 10000,
      });
      if (status !== 200) {
        throw new Error(`Request failed with code ${status}`);
      }
      if (!data.success) {
        // if register fail, print the debug msg
        logger.debug(`Grid registration error: ${data.msg}`);
      }
      return data.success;
    } catch (err) {
      logger.debug(`Hub down or not responding: ${err.message}`);
    }
  }
  
  
  export default registerNode;
  