const appium = require('appium');







const APPIUM_SERVER_READY = 'APPIUM_SERVER_READY';
const APPIUM_SERVER_SHUTDOWN = 'APPIUM_SERVER_SHUTDOWN';
const APPIUM_SERVER_LOG = 'APPIUM_SERVER_LOG';
const APPIUM_SERVER_PARENT_ALIVE = 'APPIUM_SERVER_PARENT_ALIVE';
const APPIUM_SERVER_CHECK_IN = 'APPIUM_SERVER_CHECK_IN';


const CHECK_IN_FAIL_LIMIT_MILLIS = 15_000;

const CHECK_IN_INTERVAL_MILLIS = 5_000;


const appiumConfig = JSON.parse(process.argv[2]);

if (appiumConfig.androidHome) {
  process.env.ANDROID_HOME = appiumConfig.androidHome;
  delete appiumConfig.androidHome;
}



appiumConfig.allowInsecure = ['uiautomator2:chromedriver_autodownload'];

let server;
let shutdownCalled = false;
let lastKnownCheckInTime = Date.now();
let intervalCheckIn;

appium
  .main({...appiumConfig, logHandler: logHandlerFunc})
  .then((serverInstance) => {
    server = serverInstance;
    sendMessageToParentProcess({type: APPIUM_SERVER_READY});
    lastKnownCheckInTime = Date.now();
    intervalCheckIn = global.setInterval(
      checkInOnParent,
      CHECK_IN_INTERVAL_MILLIS,
    );
  })
  .catch((error) => {
    
    throw error;
  });
process.on('message', (message) => {
  switch (message) {
        case APPIUM_SERVER_PARENT_ALIVE:
      lastKnownCheckInTime = Date.now();
      break;
    case APPIUM_SERVER_SHUTDOWN:
      shutdownCalled = true;
      server.close().catch((error) => {
        
        throw error;
      });
      break;
    default:
      console.log('unsupported message', message);
  }
});


function logHandlerFunc(logLevel, log) {
  sendMessageToParentProcess({
    type: APPIUM_SERVER_LOG,
    payload: {
      logLevel,
      log,
    },
  });
}


const originalExit = process.exit;



process.exit = (code) => {
  if (shutdownCalled) {
    global.clearInterval(intervalCheckIn);
    
    
    originalExit();
    process.kill();
  }
  if (code && code > 0) {
    const stack = new Error().stack;
    sendMessageToParentProcess({
      type: APPIUM_SERVER_LOG,
      payload: {
        logLevel: 'error',
        log: `process.exit() call prevented - ${stack}`,
      },
    });
    return;
  }
};

process.on('disconnect', () => {
  console.log(
    '[runAppiumServer.js] lost connection to parent process, terminating',
  );
  originalExit();
  process.kill();
});


function checkInOnParent() {
  try {
    sendMessageToParentProcess({type: APPIUM_SERVER_CHECK_IN});
    const currentTime = Date.now();
    const timeSinceLastCheckIn = currentTime - lastKnownCheckInTime;
    if (timeSinceLastCheckIn > CHECK_IN_FAIL_LIMIT_MILLIS) {
      console.log(
        '[runAppiumServer.js] parent process has gone dark, terminating',
      );
      global.clearInterval(intervalCheckIn);
      originalExit();
      process.kill();
    }
    lastKnownCheckInTime = currentTime;
  } catch (error) {
    console.error('Could not run checkin function', error);
  }
  return;
}


function sendMessageToParentProcess(message) {
  if (appiumConfig.runningAsUtilityProcess) {
    
    
    process.parentPort.postMessage(message);
  } else {
    process.send(message);
  }
  return;
}
