import {
  JupyterFrontEnd,
  JupyterFrontEndPlugin,
  ILayoutRestorer
} from '@jupyterlab/application';
import { IMainMenu } from '@jupyterlab/mainmenu';
import { IFileBrowserFactory } from '@jupyterlab/filebrowser';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { WidgetTracker } from '@jupyterlab/apputils';
import { DocumentWidget } from '@jupyterlab/docregistry';
import { DagEditorFactory, commandIDs } from './DagEditorWidget';
import { dagIcon } from './icons';
/**
 * @packageDocumentation
 * @module undefined
 */

const PLUGIN_ID = 'yili-dag:plugin';
const DAG_EDITOR = 'Dag Editor';
const DAG = 'dag';
const DAG_EDITOR_NAMESPACE = 'dag-editor-extension';

/**
 * Initialization data for the yili-dag extension.
 */
const plugin: JupyterFrontEndPlugin<void> = {
  id: 'yili-dag:plugin',
  autoStart: true,
  requires: [
    ILayoutRestorer,
    IFileBrowserFactory,
    IMainMenu as any,
    ISettingRegistry
  ],
  activate: async (
    app: JupyterFrontEnd,
    restorer: ILayoutRestorer,
    browserFactory: IFileBrowserFactory,
    menu: IMainMenu,
    registry: ISettingRegistry
  ) => {
    const settings = await registry
      .load(PLUGIN_ID)
      .catch(error => console.log(error));

    const dagEditorFactory = new DagEditorFactory({
      name: DAG_EDITOR,
      fileTypes: [DAG],
      defaultFor: [DAG],
      shell: app.shell,
      commands: app.commands,
      browserFactory: browserFactory,
      serviceManager: app.serviceManager,
      settings: settings
    });

    // Add the default behavior of opening the widget for .dag files
    app.docRegistry.addFileType(
      {
        name: DAG,
        displayName: 'Dag',
        extensions: ['.dag'],
        icon: dagIcon
      },
      ['JSON']
    );

    app.docRegistry.addWidgetFactory(dagEditorFactory);

    const tracker = new WidgetTracker<DocumentWidget>({
      namespace: DAG_EDITOR_NAMESPACE
    });

    dagEditorFactory.widgetCreated.connect((sender, widget) => {
      tracker.forEach(widget => {
        widget.close();
      });
      void tracker.add(widget);

      // Notify the widget tracker if restore data needs to update
      widget.context.pathChanged.connect(() => {
        void tracker.save(widget);
      });
    });

    // Handle state restoration
    void restorer.restore(tracker, {
      command: commandIDs.openDocManager,
      args: widget => ({
        path: widget.context.path,
        factory: DAG_EDITOR
      }),
      name: widget => widget.context.path
    });

    /**
     * Create new python editor from launcher and file menu
     */

    if (menu) {
      // Add new python editor creation to the file menu
      menu.fileMenu.newMenu.addGroup(
        [{ command: commandIDs.openDagEditor, args: { isMenu: true } }],
        99
      );
    }

    // Add a command to create new scala editor
    app.commands.addCommand(commandIDs.openDagEditor, {
      label: args => (args['isPalette'] ? `New ${DAG_EDITOR}` : DAG_EDITOR),
      caption: 'Create a new Dag Editor',
      icon: args => (args['isPalette'] ? undefined : dagIcon),
      execute: args => {
        // Creates blank file, then opens it in a new window
        app.commands
          .execute(commandIDs.newDocManager, {
            type: 'file',
            path: browserFactory.defaultBrowser.model.path,
            ext: '.dag'
          })
          .then(async model => {
            const dagJson = {
              id: 'uuid1',
              requirements: '',
              nodes: [],
              edges: []
            };
            const newWidget = await app.commands.execute(
              commandIDs.openDocManager,
              {
                path: model.path,
                factory: DAG_EDITOR
              }
            );
            newWidget.context.ready.then(() => {
              newWidget.context.model.fromJSON(dagJson);
              app.commands.execute(commandIDs.saveDocManager, {
                path: model.path
              });
            });
          });
      }
    });
  }
};

export default plugin;
/**
 * @packageDocumentation
 * @module undefined
 */
