// 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 { LoggingViewProvider } from './logging/view_provider';
import { ToolFinder } from './tool_finder';
import { Ffx } from './ffx';
import * as logger from './logger';
import { TargetStatusBarItem } from './target_status_bar_item';
import { FuchsiaDevice } from './ffx';
import { setUpZxdb } from './zxdb/zxdb';
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;

  constructor(ctx: vscode.ExtensionContext) {

    const toolFinder = new ToolFinder();
    this.ffx = toolFinder.ffx;
  }
}

/**
 * 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);
  setUpTargetInteraction(ctx, setup);
  setUpZxdb(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 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);
}

