// 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.

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';

import { spawn } from 'child_process';
import { disposeAnalytics, initAnalytics, setUpAnalyticsEvents } from './analytics/setup';
import { ComponentExplorerDataProvider } from './components/explorer';
import { LoggingViewProvider } from './logging/view_provider';
import { ToolFinder } from './tool_finder';
import { Ffx } from './ffx';
import { Fx } from './fx';
import * as logger from './logger';
import { TargetStatusBarItem } from './target_status_bar_item';
import { FuchsiaDevice } from './ffx';
import { setUpZxdb } from './zxdb/zxdb';
import { setUpTestController } from './testing/controller';
import * as flags from './feature-flags';

/**
 * contains common bits needed by the various setup functions below
 */
export class Setup {

  /**
   * a handle to interact with ffx
   */
  ffx: Ffx;

  /**
   * a handle to interact with fx
   */
  fx: Fx;

  constructor(ctx: vscode.ExtensionContext) {
    const toolFinder = new ToolFinder();
    this.ffx = toolFinder.ffx;
    this.fx = toolFinder.fx;
  }
}

/**
 * called automatically by vscode when activating the plugin
 * (see package.json for activation points)
 */
export async function activate(ctx: vscode.ExtensionContext) {
  flags.activate(ctx.extension.packageJSON.version);

  // Initialize the logging first so it can be used by all other code.
  const log = vscode.window.createOutputChannel('Fuchsia SDK');
  logger.initLogger(log);

  // Init analytics before possible calls to other Fuchsia tools (e.g. ffx),
  // such that the extension could display the analytics notices properly.
  try {
    await initAnalytics(ctx);
  } catch (err) {
    // if analytics fails to initialize, it's not catastrophic,
    // so just continue on after logging
    logger.error('Unable to set up analytics, boldly continuing', undefined, err);
  };
  let setup = new Setup(ctx);

  // TODO(fxbug.dev/98651): we're currently doing this every program
  // start -- we should find a better activation point
  ctx.subscriptions.push(
    vscode.commands.registerCommand('fuchsia.sendFeedback', () => {
      // The code you place here will be executed every time your command is executed
      void /* in bg */ vscode.env.openExternal(vscode.Uri.parse(
        'https://bugs.fuchsia.dev/p/fuchsia/issues/entry?template=Fuchsia+Editor+Tooling'));
    }),
  );

  setUpLoggingView(ctx, setup);
  setUpEmulatorInteraction(ctx, setup);
  setUpTargetInteraction(ctx, setup);
  setUpZxdb(ctx, setup);
  setUpComponentInteraction(ctx, setup);
  setUpTestController(ctx, setup);

  // Set up analytics events as the last step, as ffx calls in the activation process should not be
  // considered as user initiated actions.
  setUpAnalyticsEvents(setup.ffx);
}

/**
 * called automatically by vscode when deactivating the plugin
 */
export function deactivate() {
  disposeAnalytics();
  flags.deactivate();
}

/**
 * initialize the logging view & related commands
 */
function setUpLoggingView(ctx: vscode.ExtensionContext, setup: Setup) {
  // initialize the view
  const loggingProvider = new LoggingViewProvider(ctx.extensionUri, setup.ffx);
  ctx.subscriptions.push(
    vscode.window.registerWebviewViewProvider(LoggingViewProvider.viewType, loggingProvider));

  // set up command-palette commands
  ctx.subscriptions.push(
    vscode.commands.registerCommand('fuchsia.viewLogs', (device?: FuchsiaDevice) => {
      void /* in bg */ loggingProvider.resetAndShowView(device);
    })
  );
}

/**
 * initialize the target interaction commands (reboot, set target, etc)
 * and status bar item.
 */
function setUpEmulatorInteraction(ctx: vscode.ExtensionContext, setup: Setup) {
  let registerSimpleEmulatorCommand = (commandName: string,
    command: () => Promise<string>) => {
    ctx.subscriptions.push(
      vscode.commands.registerCommand(commandName,
        async () => {
          try {
            let output = await command();
            logger.info(output, 'fuchsia');
          } catch (err: any) {
            void vscode.window.showErrorMessage(err);
          }
        })
    );
  };

  registerSimpleEmulatorCommand('fuchsia.emu.start',
    setup.ffx.startEmulator.bind(setup.ffx));
  registerSimpleEmulatorCommand('fuchsia.emu.stop',
    setup.ffx.stopEmulator.bind(setup.ffx));
}

/**
 * initialize the target interaction commands (reboot, set target, etc)
 * and status bar item.
 */
function setUpTargetInteraction(ctx: vscode.ExtensionContext, setup: Setup) {
  let registerSimpleTargetCommand = (commandName: string,
    command: (device?: FuchsiaDevice) => Promise<string>) => {
    ctx.subscriptions.push(
      vscode.commands.registerCommand(commandName,
        async (device?: FuchsiaDevice) => {
          try {
            let output = await command(device);
            logger.info(output, 'fuchsia');
          } catch (err: any) {
            void vscode.window.showErrorMessage(err);
          }
        })
    );
  };
  // set up commands...
  registerSimpleTargetCommand('fuchsia.target.reboot',
    setup.ffx.rebootTarget.bind(setup.ffx));
  registerSimpleTargetCommand('fuchsia.target.show',
    setup.ffx.showTarget.bind(setup.ffx));
  registerSimpleTargetCommand('fuchsia.target.powerOff',
    setup.ffx.poweroffTarget.bind(setup.ffx));

  ctx.subscriptions.push(
    vscode.commands.registerCommand('fuchsia.target.snapshot',
      async (device?: FuchsiaDevice) => {
        let path = await setup.ffx.exportSnapshotToCWD(device);
        let msg = `snapshot exported to ${path}`;
        logger.info(msg, 'fuchsia');

        if (await vscode.window.showInformationMessage(msg, 'Open folder')) {
          spawn('xdg-open', [path]);
        }
      })
  );

  ctx.subscriptions.push(
    vscode.commands.registerCommand('fuchsia.internal.target.setDefault',
      async (device?: FuchsiaDevice) => {
        if (!device) {
          void vscode.window.showErrorMessage('A device must be selected to set as the default target.');
          return;
        }

        try {
          let output = await setup.ffx.defaultTarget(device);
          logger.debug(`Result from setting default target: ${output}`);
        } catch (err: any) {
          void vscode.window.showErrorMessage(err);
        }
      })
  );

  // ...and the status bar item
  new TargetStatusBarItem(ctx.subscriptions, setup.ffx);
}

/**
 * initialize the component interaction commands (explorer, etc)
 */
function setUpComponentInteraction(ctx: vscode.ExtensionContext, setup: Setup) {
  const componentExplorer = new ComponentExplorerDataProvider(setup.ffx);
  vscode.window.registerTreeDataProvider('vscode-fuchsia.componentExplorer', componentExplorer);
  vscode.commands.registerCommand('fuchsia.refreshComponentExplorer', () =>
    componentExplorer.refresh()
  );
}
