import * as LZString from 'lz-string';
import { NotebookModel } from '@jupyterlab/notebook';
import {
  JupyterFrontEnd,
  JupyterFrontEndPlugin,
  IRouter
} from '@jupyterlab/application';
import { UUID } from '@lumino/coreutils';
import { INotebookTracker } from '@jupyterlab/notebook';
import { ToolbarButton, Dialog, showDialog } from '@jupyterlab/apputils';
import { Clipboard } from '@jupyterlab/apputils';
import { IFileBrowserFactory } from '@jupyterlab/filebrowser';
import { Widget } from '@lumino/widgets';

import {settingsIcon} from '@jupyterlab/ui-components';

console.log('in outside new');
let savedParams: URLSearchParams | null = null;

// Save the URL parameters on page load
function saveUrlParameters(): void {
  const urlParams = new URLSearchParams(window.location.hash.slice(1));
  savedParams = urlParams;
  console.log('Saved URL parameters:', savedParams.toString());
}

// Decompress the saved URL parameter and load notebook content
function decompressSavedContent(): any | null {
  if (savedParams) {
    const compressedContent = savedParams.get('notebook');
    if (compressedContent) {
      const decompressedContent =
        LZString.decompressFromEncodedURIComponent(compressedContent);
      const content = JSON.parse(decompressedContent);
      console.log('decompressedContent', content);
      return content;
    }
  }
  return null;
}

// Add a route to render the temporary notebook
function addTempNotebookRoute(
  app: JupyterFrontEnd,
  filebrowserFactory: IFileBrowserFactory,
  router: IRouter
): void {
  if (router) {
    app.commands.addCommand('notebook:start-nav', {
      label: 'Open Temp Notebook from URL',
      execute: async args => {
        const { request } = args as IRouter.ILocation;
        const url = new URL(`http://example.com${request}`);
        const params = url.searchParams;
        const isTempNotebook = params.get('tempNotebook');

        const createFromURLRoute = async () => {
          router.routed.disconnect(createFromURLRoute);
          if (isTempNotebook && isTempNotebook == '1') {
            await app.commands.execute('notebook:open-temp', {});
          }
        };

        router.routed.connect(createFromURLRoute);
      }
    });

    app.commands.addCommand('notebook:open-temp', {
      label: 'Open Temporary Notebook',
      execute: async args => {
        const createNew = async (
          cwd: string,
          kernelId: string,
          kernelName: string
        ) => {
          const model = await app.commands.execute('docmanager:new-untitled', {
            path: cwd,
            type: 'notebook'
          });

          if (model !== undefined) {
            const widget = await app.commands.execute('docmanager:open', {
              path: model.path,
              factory: 'Notebook',
              kernel: { id: kernelId, name: kernelName }
            });

            widget.isUntitled = true;
            const tempId = `temp-notebook-${UUID.uuid4()}`;
            await widget.context.rename(tempId + '.ipynb');

            const content = decompressSavedContent();
            if (content) {
              const notebookModel = widget.context.model as NotebookModel;
              notebookModel.fromJSON(content);
              await widget.context.save();
            }

            if(settings.openAsNotebook){

            }

            updateUrlWithNotebookPath(widget.context.path);
            function updateUrlWithNotebookPath(notebookPath: string) {
              const url = new URL(window.location.href);
            
              // Get the current URL
              const currentUrl = window.location.href;
        
        
              // Extract the base URL up to /lab/index.html
              const baseUrlMatch = currentUrl.match(/(.*\/)lab\/index\.html/);
              const baseUrl = baseUrlMatch ? baseUrlMatch[1] : '';
        
              //Jupyterlite
              let retroView = baseUrl + `notebooks/index.html?path=${notebookPath}&${notebookPath}&${url.search}&${url.hash}`;
              window.location.href = retroView
            }

            
          
          

            return widget;
          }
        };

        //@ts-ignore
        const currentBrowser = filebrowserFactory?.tracker.currentWidget ?? filebrowserFactory.defaultBrowser;
        const cwd =
          (args['cwd'] as string) || (currentBrowser?.model.path ?? '');
        const kernelId = (args['kernelId'] as string) || '';
        const kernelName = (args['kernelName'] as string) || '';

        await createNew(cwd, kernelId, kernelName);
      }
    });
  }
}

async function compressNotebookContent(
  notebookPanel: any,
  settings: { copyOutput: boolean; urlPath: string; openAsNotebook: boolean }
) {
  let notebookContent: any = notebookPanel.context.model.toJSON();

  if (!settings.copyOutput) {
    notebookContent.cells = notebookContent.cells.map((cell: any) => {
      if (cell.cell_type === 'code') {
        cell.outputs = [];
        cell.execution_count = null;
      }
      return cell;
    });
  }

  const stringContent = JSON.stringify(notebookContent);

  if (stringContent.length > 10000) {
    const result = await showDialog({
      title: 'Large Notebook',
      body: 'The notebook content exceeds 10,000 characters. Do you want to continue with the full content or copy only inputs?',
      buttons: [
        Dialog.cancelButton(),
        Dialog.okButton({ label: 'Full Content' }),
        Dialog.okButton({ label: 'Inputs Only' })
      ]
    });

    if (result.button.label === 'Inputs Only') {
      notebookContent.cells = notebookContent.cells.map((cell: any) => {
        if (cell.cell_type === 'code') {
          cell.outputs = [];
          cell.execution_count = null;
        }
        return cell;
      });
    } else if (result.button.accept === false) {
      return; // User cancelled
    }
  }

  const compressedContent = LZString.compressToEncodedURIComponent(
    JSON.stringify(notebookContent)
  );

  let url: URL;

  // Function to normalize the URL
  const normalizeUrl = (inputUrl: string): string => {
    if (!inputUrl.startsWith('http://') && !inputUrl.startsWith('https://')) {
      // If no protocol is specified, assume https
      inputUrl = 'https://' + inputUrl;
    }
    // Ensure the URL ends with a trailing slash
    return inputUrl.endsWith('/') ? inputUrl : inputUrl + '/';
  };

  // Check if the urlPath is a custom URL or a predefined path
  if (settings.urlPath.includes('.') && !settings.urlPath.startsWith('/')) {
    // For custom URLs, normalize and use the entire URL as provided
    const normalizedUrl = normalizeUrl(settings.urlPath);
    url = new URL(normalizedUrl);
  } else {
    // For predefined paths, use the current location and update the pathname
    url = new URL(window.location.href);
    url.pathname = settings.urlPath;
  }

  // Add the hash and query parameters
  url.hash = `notebook=${compressedContent}`;
  url.searchParams.set('tempNotebook', '1');
  url.searchParams.set('path', 'temp.ipynb');
  
  if (settings.openAsNotebook) {
    url.searchParams.set('openAsNotebook', '1');
  }

  console.log('new url', url.toString());

  const newUrl = url.toString();
  Clipboard.copyToSystem(newUrl);
}

class SettingsDialog extends Widget {
  private settings: {
    copyOutput: boolean;
    urlPath: string;
    openAsNotebook: boolean;
  };
  private container: HTMLDivElement;

  constructor(
    private onSettingsChange: (settings: {
      copyOutput: boolean;
      urlPath: string;
      openAsNotebook: boolean;
    }) => void,
    initialSettings: {
      copyOutput: boolean;
      urlPath: string;
      openAsNotebook: boolean;
    }
  ) {
    super();
    this.settings = { ...initialSettings };
    this.container = document.createElement('div');
    this.node.appendChild(this.container);
    this.buildDialog();
  }

  private buildDialog() {
    this.container.innerHTML = ''; // Clear existing content
    this.container.style.padding = '20px';
    this.container.style.maxWidth = '400px';
    this.container.style.width = '100%';
    this.container.style.boxSizing = 'border-box';
    this.container.style.fontFamily = 'Arial, sans-serif';

    // Copy Output Switch
    const copyOutputSwitch = this.createSwitchControl(
      'Copy notebook output',
      this.settings.copyOutput,
      (checked) => this.updateSettings({ copyOutput: checked })
    );
    this.container.appendChild(copyOutputSwitch);

    // URL Path Selection
    const urlPathLabel = document.createElement('label');
    urlPathLabel.style.display = 'block';
    urlPathLabel.style.marginTop = '20px';
    urlPathLabel.style.marginBottom = '8px';
    urlPathLabel.style.fontWeight = 'bold';
    urlPathLabel.textContent = 'URL path:';
    this.container.appendChild(urlPathLabel);

    const urlPathSelect = document.createElement('select');
    urlPathSelect.style.width = '100%';
    urlPathSelect.style.padding = '8px';
    urlPathSelect.style.marginBottom = '15px';
    urlPathSelect.style.borderRadius = '4px';
    urlPathSelect.style.border = '1px solid #ccc';

    const paths = [
      { label: 'JupyterLite', value: '/jupyterlite/lab/index.html', openAsNotebook: false },
      { label: 'JupyterLite Notebook', value: '/jupyterlite/lab/index.html', openAsNotebook: true },
      { label: 'JupyterLab', value: '/lab/index.html', openAsNotebook: false },
      { label: 'Custom', value: 'custom', openAsNotebook: false }
    ];

    paths.forEach(path => {
      const option = document.createElement('option');
      option.value = JSON.stringify(path);
      option.textContent = path.label;
      if (path.value === this.settings.urlPath && path.openAsNotebook === this.settings.openAsNotebook) {
        option.selected = true;
      }
      urlPathSelect.appendChild(option);
    });

    this.container.appendChild(urlPathSelect);

    // URL display
    const urlDisplay = document.createElement('p');
    urlDisplay.style.fontSize = '0.9em';
    urlDisplay.style.color = '#666';
    urlDisplay.style.marginTop = '10px';
    urlDisplay.style.marginBottom = '15px';
    urlDisplay.style.wordBreak = 'break-all';
    this.container.appendChild(urlDisplay);

    // Custom URL input (initially hidden)
    const customUrlInput = document.createElement('input');
    customUrlInput.type = 'text';
    customUrlInput.placeholder = 'Enter custom URL path';
    customUrlInput.style.width = '100%';
    customUrlInput.style.padding = '8px';
    customUrlInput.style.marginTop = '10px';
    customUrlInput.style.display = 'none';
    customUrlInput.style.boxSizing = 'border-box';
    customUrlInput.style.borderRadius = '4px';
    customUrlInput.style.border = '1px solid #ccc';
    this.container.appendChild(customUrlInput);

    // Warning message for custom URL (initially hidden)
    const warningMessage = document.createElement('p');
    warningMessage.textContent = 'Warning: nblink must be installed on the Jupyter instance for custom URLs.';
    warningMessage.style.color = 'orange';
    warningMessage.style.fontSize = '0.9em';
    warningMessage.style.display = 'none';
    warningMessage.style.marginTop = '10px';
    this.container.appendChild(warningMessage);

    // Event listener for URL path selection
    urlPathSelect.addEventListener('change', () => {
      const selectedOption = JSON.parse(urlPathSelect.value);
      if (selectedOption.value === 'custom') {
        customUrlInput.style.display = 'block';
        warningMessage.style.display = 'block';
        urlDisplay.textContent = '';
        customUrlInput.value = ''; // Clear the input when switching to custom
      } else {
        customUrlInput.style.display = 'none';
        warningMessage.style.display = 'none';
        this.updateSettings({ 
          urlPath: selectedOption.value, 
          openAsNotebook: selectedOption.openAsNotebook 
        });
        this.updateUrlDisplay(urlDisplay, selectedOption.value, false);
      }
    });

    // Event listener for custom URL input
    customUrlInput.addEventListener('input', () => {
      this.updateSettings({ 
        urlPath: customUrlInput.value, 
        openAsNotebook: false 
      });
      this.updateUrlDisplay(urlDisplay, customUrlInput.value, true);
    });

    // Initial URL display update
    this.updateUrlDisplay(urlDisplay, this.settings.urlPath, this.settings.urlPath === 'custom');
  }

  private createSwitchControl(label: string, initialState: boolean, onChange: (checked: boolean) => void) {
    const container = document.createElement('label');
    container.style.display = 'flex';
    container.style.alignItems = 'center';
    container.style.marginBottom = '15px';
    container.style.cursor = 'pointer';

    const switchElem = document.createElement('div');
    switchElem.style.width = '40px';
    switchElem.style.height = '20px';
    switchElem.style.backgroundColor = initialState ? '#4CAF50' : '#ccc';
    switchElem.style.borderRadius = '10px';
    switchElem.style.position = 'relative';
    switchElem.style.transition = 'background-color 0.3s';
    switchElem.style.marginRight = '10px';

    const switchHandle = document.createElement('div');
    switchHandle.style.width = '18px';
    switchHandle.style.height = '18px';
    switchHandle.style.backgroundColor = 'white';
    switchHandle.style.borderRadius = '50%';
    switchHandle.style.position = 'absolute';
    switchHandle.style.top = '1px';
    switchHandle.style.left = initialState ? '21px' : '1px';
    switchHandle.style.transition = 'left 0.3s';

    switchElem.appendChild(switchHandle);
    container.appendChild(switchElem);
    container.appendChild(document.createTextNode(label));

    container.addEventListener('click', () => {
      const newState = switchHandle.style.left === '1px';
      switchHandle.style.left = newState ? '21px' : '1px';
      switchElem.style.backgroundColor = newState ? '#4CAF50' : '#ccc';
      onChange(newState);
    });

    return container;
  }

  private updateSettings(partialSettings: Partial<{ copyOutput: boolean; urlPath: string; openAsNotebook: boolean }>) {
    this.settings = { ...this.settings, ...partialSettings };
    this.onSettingsChange(this.settings);
  }

  private updateUrlDisplay(element: HTMLElement, urlPath: string, isCustom: boolean) {
    if (isCustom) {
      element.textContent = `Links to: ${urlPath}`;
    } else {
      const baseUrl = window.location.href.split('/lab')[0];
      element.textContent = `Links to: ${baseUrl}${urlPath}`;
    }
  }
}

let settings = {
  copyOutput: false, openAsNotebook: true, urlPath:'/lab/index.html'
};


// class SplitButton extends Widget {
//   constructor(
//     private saveAction: () => void,
//     private settingsAction: () => void
//   ) {
//     super();
//     this.addClass('jp-SplitButton');
//     this.buildWidget();
//   }

//   private buildWidget() {
//     const container = document.createElement('div');
//     container.className = 'jp-SplitButton-container';

//     const mainButton = new ToolbarButton({
//       className: 'jp-SplitButton-main',
//       label: 'Save to URL',
//       onClick: this.saveAction,
//       tooltip: 'Save notebook content to URL and copy to clipboard'
//     });

//     const settingsButton = new ToolbarButton({
//       className: 'jp-SplitButton-secondary',
//       icon: settingsIcon,
//       onClick: this.settingsAction,
//       tooltip: 'Save to URL Settings'
//     });

//     container.appendChild(mainButton.node);
//     container.appendChild(settingsButton.node);
//     this.node.appendChild(container);
//   }
// }

// In your main extension file:
// function addSaveToUrlButton(
//   app: JupyterFrontEnd,
//   notebookTracker: INotebookTracker
// ) {
//   let settings = {
//     copyOutput: false,
//     urlPath: '/jupyterlite/lab/index.html',
//     openAsNotebook: false
//   };

//   const saveAction = () => {
//     const current = notebookTracker.currentWidget;
//     console.log('in press', current, settings);
//     if (current) {
//       compressNotebookContent(current, settings);
//     }
//   };

//   const settingsAction = () => {
//     const dialog = new SettingsDialog(newSettings => {
//       settings = newSettings;
//       dialog.dispose();
//     }, settings);

//     showDialog({
//       title: 'Save to URL Settings',
//       body: dialog,
//       buttons: [Dialog.cancelButton()]
//     });
//   };

//   const splitButton = new SplitButton(saveAction, settingsAction);

//   notebookTracker.widgetAdded.connect((sender, panel) => {
//     console.log('added', splitButton, panel.toolbar);
//     panel.toolbar.insertItem(10, 'saveToUrl', splitButton);
//   });
// }

// Add "Save to URL" dropdown button to the notebook toolbar
function addSaveToUrlButton(
  app: JupyterFrontEnd,
  notebookTracker: INotebookTracker
) {

  

  const saveToUrlButton = new ToolbarButton({
    label: 'Save to url',
    onClick: () => {
      const current = notebookTracker.currentWidget;
      console.log('in press', current, settings);
      if (current) {
        compressNotebookContent(current, settings);
      }
    },
    tooltip: 'Save notebook content to URL and copy to clipboard'
  });

  const settingsButton = new ToolbarButton({
    icon: settingsIcon,
    //label: 'setting',
    onClick: () => {
      const dialog = new SettingsDialog(newSettings => {
        settings = newSettings;
        //dialog.dispose();
      }, settings);

      showDialog({
        title: 'Save to URL Settings',
        body: dialog,
        buttons: [Dialog.okButton()]
      });
    },
    tooltip: 'Save to URL Settings'
  });
  
  notebookTracker.widgetAdded.connect((sender, panel) => {
    console.log('added',saveToUrlButton, settingsButton, panel.toolbar)

    panel.toolbar.insertItem(10, 'saveToUrl', saveToUrlButton);
    panel.toolbar.insertItem(11, 'settingsButton', settingsButton);

  });

}

const extension: JupyterFrontEndPlugin<void> = {
  id: 'nblink',
  autoStart: true,
  requires: [IFileBrowserFactory, IRouter, INotebookTracker],
  activate: async (
    app: JupyterFrontEnd,
    filebrowserFactory: IFileBrowserFactory,
    router: IRouter,
    notebookTracker: INotebookTracker
  ) => {
    try {
      console.log('Activating nblink extension: new');

      router.register({
        command: 'notebook:start-nav',
        pattern: /(tempNotebook=1)/,
        rank: 20
      });

      addSaveToUrlButton(app, notebookTracker);
      saveUrlParameters();
      await addTempNotebookRoute(app, filebrowserFactory, router);

      console.log('nblink extension activated successfully');
    } catch (error) {
      console.error('Error activating nblink extension:', error);
    }
  }
};

export default extension;
