text: const fsuipc = require('fsuipc');
  const dgram = require('dgram');
  const fs = require('fs');
  const path = require('path');
  const logger = require('./logger');
  
  const fsuipcInstance = new fsuipc.FSUIPC();
  const xpClient = dgram.createSocket('udp4');
  var trackingXP = false;
  
  const getSimData = () => {
    logger.info('Simulator data was requested...');
    return fsuipcInstance.open().then((thisInstance) => {
      thisInstance.add('aircraft_type', 0x3D00, fsuipc.Type.String, 256);
      thisInstance.add('latitude', 0x6010, fsuipc.Type.Double, 8);
      thisInstance.add('longitude', 0x6018, fsuipc.Type.Double, 8);
      thisInstance.add('altitude', 0x6020, fsuipc.Type.Double);
      thisInstance.add('verticalSpeed', 0x02C8, fsuipc.Type.Int32);
      thisInstance.add('landingRate', 0x030C, fsuipc.Type.Int32);
      thisInstance.add('gear', 0x0BE8, fsuipc.Type.Int32);
      thisInstance.add('flaps', 0x3414, fsuipc.Type.Int32);
      thisInstance.add('stall', 0x036C, fsuipc.Type.Byte);
      thisInstance.add('slew', 0x05DC, fsuipc.Type.Int32);
      thisInstance.add('overspeed', 0x036D, fsuipc.Type.Byte);
      thisInstance.add('empty', 0x1330, fsuipc.Type.Int32);
      thisInstance.add('zfw', 0x3BFC, fsuipc.Type.Int32);
      thisInstance.add('currentFuel', 0x126C, fsuipc.Type.Int32);
      
      return thisInstance.process();
    }).then(async (result) => {
      let finRes = {
        aircraft_type: result.aircraft_type,
        latitude: result.latitude,
        longitude: result.longitude,
        altitude: parseFloat((result.altitude * 3.28084).toFixed(2)),
        verticalSpeed: result.verticalSpeed,
        landingRate: result.landingRate,
        gear: result.gear,
        overspeed: result.overspeed,
        slew: result.slew,
        stall: result.stall,
        flaps: result.flaps,
        zfw: parseInt((result.zfw / 256 / 2.025).toFixed()),
        empty: parseInt((result.empty / 256 / 2.025).toFixed()),
        currentFuel: parseInt((result.currentFuel / 2.025).toFixed())
      }
      await fsuipcInstance.close();
      if (finRes.latitude !== 0 && finRes.longitude !== 0) return finRes;
      else { 
        logger.warn('FSUIPC data unavailable, requesting X-Plane Data Refs.');
        if (!trackingXP) {
          getXPdata();
          setTimeout(() => {
            return JSON.parse(fs.readFileSync(path.join('./', 'xpData.json')));
          }, 1001);
        } else {
          return JSON.parse(fs.readFileSync(path.join('./', 'xpData.json')));
        }
      }
    }).catch(async () => {
      await fsuipcInstance.close();
      logger.warn('FSUIPC data unavailable, requesting X-Plane Data Refs.');
      if (!trackingXP) {
        getXPdata();
        setTimeout(() => {
          return JSON.parse(fs.readFileSync(path.join('./', 'xpData.json')));
        }, 1001);
      } else {
        return JSON.parse(fs.readFileSync(path.join('./', 'xpData.json')));
      }
    });
  }
  
  const getXPdata = () => {
    if (trackingXP && JSON.parse(fs.readFileSync(path.join('./', 'xpData.json'))).aircraft_type) return;
    trackingXP = true;
    const PORT = 49000;
    const HOST = '127.0.0.1';
    const FREQ = 1;
  
    const createDataMessage = (dref, idx, freq) => {
      const message = Buffer.alloc(413);
      message.write('RREF\0');
      message.writeInt8(freq, 5);
      message.writeInt8(idx, 9);
      message.write(dref, 13);
      return message;
    }
  
    const messages = [
      createDataMessage('sim/flightmodel/position/latitude', 1, FREQ), //lat
      createDataMessage('sim/flightmodel/position/longitude', 1, FREQ), //lon
      createDataMessage('sim/flightmodel/misc/h_ind', 1, FREQ), //alt
      createDataMessage('sim/flightmodel/position/vh_ind_fpm', 1, FREQ), //vs
      createDataMessage('sim/cockpit/switches/gear_handle_status', 1, FREQ), //gear
      createDataMessage('sim/flightmodel/controls/flaprqst', 1, FREQ), //flaps
      createDataMessage('sim/flightmodel/failures/stallwarning', 1, FREQ), //stall
      createDataMessage('sim/flightmodel/weight/m_fixed', 1, FREQ), //payload mass
      createDataMessage('sim/aircraft/weight/acf_m_empty', 1, FREQ), //empty mass
      createDataMessage('sim/flightmodel/weight/m_fuel_total', 1, FREQ), //current fuel
    ];
  
    let fsData = {};
  
    xpClient.on('message', (message, remote) => {
      const label = message.toString('utf8', 0, 4);
      if (label !== 'RREF') {
        console.log('Unknown package. Ignoring');
      } else {
        let offset = 9;
        let messages = [];
  
        while (offset < message.length) {
          const value = message.readFloatLE(offset);
          messages.push(value);
          offset += 8;
        }
  
        let prevData = JSON.parse(fs.readFileSync(path.join('./', 'xpData.json')));
  
        fsData = {
          aircraft_type: 'N/A',
          latitude: messages[0] || prevData.latitude,
          longitude: messages[1] || prevData.longitude,
          altitude: parseFloat(messages[2]?.toFixed(2)) || prevData.altitude,
          verticalSpeed: parseInt(messages[3]?.toFixed()) || prevData.verticalSpeed || 0,
          gear: messages[4] || prevData.gear,
          overspeed: 0,
          slew: 0,
          stall: messages[6] || prevData.stall,
          flaps: (messages[5] || 0) * 16384 || prevData.flaps,
          zfw: parseInt((messages[7] + messages[8])?.toFixed()) || prevData.zfw,
          empty: parseInt(messages[8]?.toFixed()) || prevData.empty,
          currentFuel: parseInt(messages[9]?.toFixed()) || prevData.currentFuel,
          xp11Signature: true,
          time: new Date().getTime()
        };
  
        fsData.landingRate = fsData.verticalSpeed;
  
        fs.writeFileSync(path.join('./', 'xpData.json'), JSON.stringify(fsData, null, 4));
      }
    });
  
    for (let i = 0; i < messages.length; i++) {
      xpClient.send(messages[i], 0, messages[i].length, PORT, HOST, (err, bytes) => {
        if (err) {
          logger.error('Error in XP Data Refs', err)
        }
      });
    }
  }
  
  const closeXPconnection = () => xpClient.close();
  
  module.exports = { getSimData, getXPdata, closeXPconnection };