// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import assert from 'assert'; // not esm
import * as vscode from 'vscode';
import { beforeEach, describe, it } from 'mocha';
import { createSandbox } from 'sinon';

import { Ffx, FfxEventType, FuchsiaDevice } from '../../ffx';
import * as logger from '../../logger';

import { StubbedSpawn } from './utils';

describe('FuchsiaDevice', function () {
  describe('#constructor()', function () {
    it('creates an instance of FuchsiaDevice from the json returned from ffx target list',
      function () {
        const data = {
          'nodename': 'test-device',
          // eslint-disable-next-line @typescript-eslint/naming-convention
          'rcs_state': 'Y',
          'serial': '<unknown>',
          // eslint-disable-next-line @typescript-eslint/naming-convention
          'target_type': 'workstation.qemu-x64',
          // eslint-disable-next-line @typescript-eslint/naming-convention
          'target_state': 'Product',
          'addresses': ['fe80::3bee:1d4:e205:777e%brqemu', '172.1.1.1']
        };

        let device = new FuchsiaDevice(data);
        assert.strictEqual(device.nodeName, data['nodename']);
        assert.strictEqual(device.rcsState, data['rcs_state']);
        assert.strictEqual(device.serial, data['serial']);
        assert.strictEqual(device.targetType, data['target_type']);
        assert.strictEqual(device.targetState, data['target_state']);
        let testAddresses = data['addresses'];
        let actualAddresses = device.addresses;
        for (let i in testAddresses) {
          assert.strictEqual(testAddresses[i], actualAddresses[i]);
        }
      });
  });
});

describe('Ffx', function () {
  const sandbox = createSandbox();
  const TEST_FFX = '/path/to/ffx';
  const TEST_CWD = '/path/to/workspace';
  const ANALYTICS_FLAG = ['--config', 'fuchsia.analytics.ffx_invoker=vscode-fuchsia'];
  var stubbedSpawn: StubbedSpawn;

  this.beforeEach(function () {
    stubbedSpawn = new StubbedSpawn(sandbox);
    const log = vscode.window.createOutputChannel('tool_finder.test');
    logger.initLogger(log);
  });

  this.afterEach(function () {
    sandbox.restore();
  });
  describe('#constructor', function () {
    it('creates an instance of ffx', function () {
      new Ffx(TEST_CWD, TEST_FFX);
    });
  });

  describe('#rebootTarget', function () {
    it('calls ffx target reboot for the default device successfully', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let promise = ffx.rebootTarget();
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, 'target', 'reboot'], { cwd: TEST_CWD, detached: true }]);
    });

    it('calls ffx target reboot for the default device and fails', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      const errorMessage = 'Cannot reboot device';

      await assert.rejects(async () => {
        let promise = ffx.rebootTarget();
        stubbedSpawn.spawnEvent.stderr?.emit('data', errorMessage);
        stubbedSpawn.spawnEvent.emit('exit', 1);
        stubbedSpawn.spawnEvent.emit('close', 1);
        await promise;
      }, new Error(`ffx returned with non-zero exit code 1: ${errorMessage}`));
    });

    it('calls ffx target reboot the specified device', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let device = new FuchsiaDevice({ 'nodename': 'test-device' });
      let promise = ffx.rebootTarget(device);
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(stubbedSpawn.spawnStubInfo.getCall(0).args, [
        TEST_FFX, [...ANALYTICS_FLAG, '--target', 'test-device', 'target', 'reboot'],
        { cwd: TEST_CWD, detached: true }
      ]);
    });
  });

  describe('#PoweroffTarget', function () {
    it('calls ffx target off for the default device successfully', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let promise = ffx.poweroffTarget();
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, 'target', 'off'], { cwd: TEST_CWD, detached: true }]);
    });

    it('calls ffx target off for the default device and fails', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      const errorMessage = 'Cannot power off the device';

      await assert.rejects(async () => {
        let promise = ffx.poweroffTarget();
        stubbedSpawn.spawnEvent.stderr?.emit('data', errorMessage);
        stubbedSpawn.spawnEvent.emit('exit', 1);
        stubbedSpawn.spawnEvent.emit('close', 1);
        await promise;
      }, new Error(`ffx returned with non-zero exit code 1: ${errorMessage}`));
    });

    it('calls ffx target off the specified device', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let device = new FuchsiaDevice({ 'nodename': 'test-device' });
      let promise = ffx.poweroffTarget(device);
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(stubbedSpawn.spawnStubInfo.getCall(0).args, [
        TEST_FFX, [...ANALYTICS_FLAG, '--target', 'test-device', 'target', 'off'],
        { cwd: TEST_CWD, detached: true }
      ]);
    });
  });


  describe('#showTarget', function () {
    it('calls ffx target show for the default device successfully', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let promise = ffx.showTarget();
      // normal exit, no output.
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;

      assert.strictEqual(output, '');
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, 'target', 'show'], { cwd: TEST_CWD, detached: true }]);
    });

    it('calls ffx target show for the default device and fails', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      const errorMessage = 'Cannot reboot device';

      await assert.rejects(async () => {
        let promise = ffx.showTarget();
        stubbedSpawn.spawnEvent.stderr?.emit('data', errorMessage);
        stubbedSpawn.spawnEvent.emit('exit', 1);
        stubbedSpawn.spawnEvent.emit('close', 1);
        await promise;
      }, new Error(`ffx returned with non-zero exit code 1: ${errorMessage}`));
    });

    it('calls ffx target show for the specified device', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let device = new FuchsiaDevice({ 'nodename': 'test-device' });
      let promise = ffx.showTarget(device);
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(stubbedSpawn.spawnStubInfo.getCall(0).args, [
        TEST_FFX, [...ANALYTICS_FLAG, '--target', 'test-device', 'target', 'show'],
        { cwd: TEST_CWD, detached: true }
      ]);
    });
  });

  describe('#ExportSnapshot', function () {
    it('calls ffx target snapshot for the default device successfully', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let promise = ffx.exportSnapshotToCWD();
      // normal exit, no output.
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;

      assert.strictEqual(output, TEST_CWD);
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, 'target', 'snapshot', '-d', TEST_CWD],
          { cwd: TEST_CWD, detached: true }]);
    });

    it('calls ffx target snapshot for the default device and fails', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      const errorMessage = 'Cannot reboot device';

      await assert.rejects(async () => {
        let promise = ffx.exportSnapshotToCWD();
        stubbedSpawn.spawnEvent.stderr?.emit('data', errorMessage);
        stubbedSpawn.spawnEvent.emit('exit', 1);
        stubbedSpawn.spawnEvent.emit('close', 1);
        await promise;
      }, new Error(`ffx returned with non-zero exit code 1: ${errorMessage}`));
    });

    it('calls ffx target snapshot for the specified device', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let device = new FuchsiaDevice({ 'nodename': 'test-device' });
      let promise = ffx.exportSnapshotToCWD(device);
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, TEST_CWD);
      assert.deepStrictEqual(stubbedSpawn.spawnStubInfo.getCall(0).args, [
        TEST_FFX,
        [...ANALYTICS_FLAG, '--target', 'test-device', 'target', 'snapshot', '-d', TEST_CWD],
        { cwd: TEST_CWD, detached: true }
      ]);
    });
  });

  describe('#defaultTarget', function () {
    it('sets the specified device to be the default target', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);
      let device = new FuchsiaDevice({ 'nodename': 'test-device' });
      let promise = ffx.defaultTarget(device);
      stubbedSpawn.spawnEvent.emit('exit', 0);
      stubbedSpawn.spawnEvent.emit('close', 0);
      let output = await promise;
      assert.strictEqual(output, '');
      assert.deepStrictEqual(stubbedSpawn.spawnStubInfo.getCall(0).args, [
        TEST_FFX,
        [...ANALYTICS_FLAG, 'target', 'default', 'set', 'test-device'],
        { cwd: TEST_CWD, detached: true }
      ]);
    });
  });

  describe('#events', function () {
    it('Verify set path events', () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);
      let lastEvent: FfxEventType | undefined;
      ffx.onDidChangeConfiguration(event => {
        lastEvent = event;
      });
      ffx.path = TEST_FFX;
      assert.strictEqual(lastEvent, FfxEventType.ffxPathSet);
      ffx.path = undefined;
      assert.strictEqual(lastEvent, FfxEventType.ffxPathReset);
      ffx.path = TEST_FFX;
      assert.strictEqual(lastEvent, FfxEventType.ffxPathSet);
    });
  });

  describe('#getTargetList', function () {
    // targetListData: Targets = 2, DefaultTargetCount = 1, ConnectedTargetCount = 2
    const targetListData = [
      {
        'nodename': 'test-device',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'Y',
        'serial': 'serial-11111',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'target_type': 'test-product',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'target_state': 'Product',
        'addresses': ['fe80::41e7:ace8:59b7:3cb7%en11'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': false
      },
      {
        'nodename': 'another-device',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'Y',
        'serial': 'serial-222222',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'target_type': 'test-product',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'target_state': 'Product',
        'addresses': ['fe80::1010:1010:1010:1010%en11'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': true
      }
    ];

    // newTargetList: Targets = 3, DefaultTargetCount = 1, ConnectedTargetCount = 2
    const newTargetList = [
      {
        'nodename': 'dev1',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'Y',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'serial': 'na', 'target_type': 'na', 'target_state': 'na', 'addresses': ['127.0.0.1'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': true
      },
      {
        'nodename': 'dev2',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'Y',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'serial': 'na', 'target_type': 'na', 'target_state': 'na', 'addresses': ['127.0.0.1'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': false
      },
      {
        'nodename': 'dev3',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'N',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'serial': 'na', 'target_type': 'na', 'target_state': 'na', 'addresses': ['127.0.0.1'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': false
      }
    ];

    // newTargetListError: Targets = 2, DefaultTargetCount = 0, ConnectedTargetCount = 0
    const newTargetListError = [
      {
        'nodename': '<unknown1>',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'N',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'serial': 'na', 'target_type': 'na', 'target_state': 'na', 'addresses': ['127.0.0.1'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': false
      },
      {
        'nodename': '<unknown2>',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'rcs_state': 'N',
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'serial': 'na', 'target_type': 'na', 'target_state': 'na', 'addresses': ['127.0.0.1'],
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'is_default': false
      }
    ];

    /**
     * Get first default target name
     * @param targetList
     * @returns target name or undefine
     */
    function defaultTarget(targetList: { [key: string]: FuchsiaDevice; }) {
      return Object.values(targetList).map(e => e.isDefault ? e.nodeName : undefined)
        .reduce<string | undefined>((acc, cur) => acc ?? cur, undefined);
    }

    /**
     * Returns the number of devices that are set to default, should be 0 or 1.
     * @param targetList
     * @returns default device count
     */
    function defaultTargetCount(targetList: { [key: string]: FuchsiaDevice; }) {
      return Object.values(targetList).map(e => e.isDefault ? 1 : 0)
        .reduce<number>((acc, cur) => acc + cur, 0);
    }

    /**
     * Return the number of devices that we can connect to
     * @param targetList
     * @returns number of available devices
     */
    function connectedTargetCount(targetList: { [key: string]: FuchsiaDevice; }) {
      return Object.values(targetList).map(e => e.rcsState === 'Y' ? 1 : 0)
        .reduce<number>((acc, cur) => acc + cur, 0);
    }

    const TARGET_LIST_ARGS = ['--machine', 'json', 'target', 'list'];

    it('gets a map of device name to FuchsiaDevice.', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      stubbedSpawn.spawnStubInfo.callsFake(function () {
        setTimeout(() => {
          stubbedSpawn.spawnEvent.stdout?.emit('data', JSON.stringify(targetListData));
          stubbedSpawn.spawnEvent.emit('exit', 0);
          stubbedSpawn.spawnEvent.emit('close', 0);
        }, 1);
        return stubbedSpawn.spawnEvent;
      });

      let deviceList = await ffx.getTargetList();

      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, ...TARGET_LIST_ARGS], { cwd: TEST_CWD, detached: true }]);

      // targetListData: Targets = 2, DefaultTargetCount = 1, ConnectedTargetCount = 2
      assert.strictEqual(Object.keys(deviceList).length, 2);
      assert.strictEqual(defaultTargetCount(deviceList), 1);
      assert.strictEqual(connectedTargetCount(deviceList), 2);
      assert.strictEqual(defaultTarget(deviceList), 'another-device');
    });

    it('Timeout while calling FFX Target List', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      stubbedSpawn.spawnStubInfo.callsFake(function () {
        return stubbedSpawn.spawnEvent;
      });

      await vscode.workspace.getConfiguration('fuchsia').update('connectionTimeout', 10);
      try {
        await ffx.getTargetList();
      } catch (e) {
        assert.deepStrictEqual(true, e instanceof Error);
        if (e instanceof Error) {
          assert.strictEqual(true, e.toString().includes('timeout'), `"timeout" is not in "${e}"`);
          return;
        }
      }
      throw Error('Target list does not timeout!');
    });

    /**
     * Send two FFX target lists sequentially and get the final IDE device list
     * @param testDataOne first target list returned by FFX target list
     * @param testDataTwo second target list returned by FFX target list
     * @returns a promise to the final IDE device list
     */
    async function setupTwoDeviceListTest(testDataOne: string, testDataTwo: string) {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      let useTestDataTwo = false;
      stubbedSpawn.spawnStubInfo.callsFake(function () {
        setTimeout(() => {
          let data = useTestDataTwo ? testDataTwo : testDataOne;
          stubbedSpawn.spawnEvent.stdout?.emit('data', data);
          stubbedSpawn.spawnEvent.emit('exit', 0);
          stubbedSpawn.spawnEvent.emit('close', 0);
        }, 1);
        return stubbedSpawn.spawnEvent;
      });

      let deviceList = await ffx.getTargetList();

      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, ...TARGET_LIST_ARGS], { cwd: TEST_CWD, detached: true }]);

      // check number of devices
      assert.strictEqual(Object.keys(deviceList).length, targetListData.length);

      //Use test data 2 on second call
      useTestDataTwo = true;
      deviceList = await ffx.getTargetList();

      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(1).args,
        [TEST_FFX, [...ANALYTICS_FLAG, ...TARGET_LIST_ARGS], { cwd: TEST_CWD, detached: true }]);

      return deviceList;
    }

    it('Verify device list after targetListData and then empty', async () => {
      let deviceList = await setupTwoDeviceListTest(JSON.stringify(targetListData), '');

      // Empty device list
      assert.strictEqual(Object.keys(deviceList).length, 0);
    });

    it('Verify device list after targetListData and then newTargetList', async () => {
      let deviceList = await setupTwoDeviceListTest(
        JSON.stringify(targetListData),
        JSON.stringify(newTargetList)
      );

      // newTargetList: Targets = 3, DefaultTargetCount = 1, ConnectedTargetCount = 2
      assert.strictEqual(Object.keys(deviceList).length, 3);
      assert.strictEqual(defaultTargetCount(deviceList), 1);
      assert.strictEqual(connectedTargetCount(deviceList), 2);
      assert.strictEqual(defaultTarget(deviceList), 'dev1');
    });

    it('Verify device list after targetListData and then newTargetListError', async () => {
      let deviceList = await setupTwoDeviceListTest(
        JSON.stringify(targetListData),
        JSON.stringify(newTargetListError)
      );

      // newTargetListError: Targets = 2, DefaultTargetCount = 0, ConnectedTargetCount = 0
      assert.strictEqual(Object.keys(deviceList).length, 2);
      assert.strictEqual(defaultTargetCount(deviceList), 0);
      assert.strictEqual(connectedTargetCount(deviceList), 0);
      assert.strictEqual(defaultTarget(deviceList), undefined);
    });

    it('gets a map of device name to FuchsiaDevice and gets the default.', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      stubbedSpawn.spawnStubInfo.callsFake(function () {
        setTimeout(() => {
          stubbedSpawn.spawnEvent.stdout?.emit('data', JSON.stringify(targetListData));
          stubbedSpawn.spawnEvent.emit('exit', 0);
          stubbedSpawn.spawnEvent.emit('close', 0);
        }, 1);
        return stubbedSpawn.spawnEvent;
      });

      let deviceList = await ffx.getTargetList();
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, ...TARGET_LIST_ARGS], { cwd: TEST_CWD, detached: true }]);

      // check number of devices
      assert.strictEqual(Object.keys(deviceList).length, targetListData.length);

      // check there is no default.
      for (let name in deviceList) {
        assert.strictEqual(
          deviceList[name].isDefault, deviceList[name].nodeName === 'another-device');
      }
    });

    it('Verify set target event', async () => {
      const ffx = new Ffx(TEST_CWD, TEST_FFX);

      stubbedSpawn.spawnStubInfo.callsFake(function () {
        setTimeout(() => {
          stubbedSpawn.spawnEvent.stdout?.emit('data', JSON.stringify(targetListData));
          stubbedSpawn.spawnEvent.emit('exit', 0);
          stubbedSpawn.spawnEvent.emit('close', 0);
        }, 1);
        return stubbedSpawn.spawnEvent;
      });

      let count = 0;
      ffx.onSetTarget(target => {
        count += 1;
      });

      assert.strictEqual(count, 0);
      ffx.path = TEST_FFX;
      await new Promise(resolve => setTimeout(resolve, 50));
      assert.strictEqual(count, 1);
    });
  });

  describe('#runLog', () => {
    let ffx: Ffx;

    const LOG_ARGS = ['--target', 'foo', '--machine', 'json', 'log'];
    beforeEach(() => {
      ffx = new Ffx(TEST_CWD, TEST_FFX);
    });

    it('parses stdout and sends it to the callback', () => {
      let received;
      const TEST_DATA: Object = { 'foo': 'bar' };
      stubbedSpawn.spawnStubInfo.callsFake(() => stubbedSpawn.spawnEvent);
      ffx.runLog('foo', [], (data) => {
        received = data;
      });
      assert.deepStrictEqual(
        stubbedSpawn.spawnStubInfo.getCall(0).args,
        [TEST_FFX, [...ANALYTICS_FLAG, ...LOG_ARGS], { cwd: TEST_CWD, detached: true }]);
      stubbedSpawn.spawnEvent.stdout?.emit('data', JSON.stringify(TEST_DATA));
      assert.deepStrictEqual(received, TEST_DATA);
    });

    it('sends stderr to the log', () => {
      stubbedSpawn.spawnStubInfo.callsFake(() => stubbedSpawn.spawnEvent);
      // spy on the singleton instead of the module method, since we can't
      // modify singletons and such with ESM
      let spiedWarn = sandbox.spy(logger.logger, 'warn');
      ffx.runLog('foo', [], (_) => { });
      stubbedSpawn.spawnEvent.stderr?.emit('data', 'oh no');
      assert(spiedWarn.calledOnce);
      assert(
        spiedWarn.getCall(0).args[0].endsWith('oh no'));
    });
  });
});
