import * as React from 'react';
import { ReactWidget } from '@jupyterlab/apputils';
import { ServerConnection } from '@jupyterlab/services';

import { getSnapshotContent } from '../api';
import { INotebook } from '../diff';
import { SnapshotModel } from '../model';
import { CommandIDs } from '../commands';
import { JupyterFrontEnd } from '@jupyterlab/application';
import { INotebookTracker } from '@jupyterlab/notebook';

function formatTimestamp(ts: number): string {
  // timestamp is microseconds (see backend store.py)
  const ms = ts / 1000;
  return new Date(ms).toLocaleString();
}

function formatSize(bytes: number): string {
  if (bytes < 1024) {
    return `${bytes} B`;
  }
  if (bytes < 1024 * 1024) {
    return `${(bytes / 1024).toFixed(1)} KB`;
  }
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}

interface PanelProps {
  model: SnapshotModel;
  app: JupyterFrontEnd;
  tracker: INotebookTracker;
  serverSettings: ServerConnection.ISettings;
  onOpenDiff: (newNb: INotebook, oldNb: INotebook, name: string) => void;
}

const Panel: React.FC<PanelProps> = ({ model, app, tracker, serverSettings, onOpenDiff }) => {
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    const onChange = () => force();
    model.versionsChanged.connect(onChange);
    return () => {
      model.versionsChanged.disconnect(onChange);
    };
  }, [model]);

  if (!model.path) {
    return <div className="jp-snapshot-panel-empty">未选中 notebook</div>;
  }
  if (model.loading && model.versions.length === 0) {
    return <div className="jp-snapshot-panel-empty">加载中…</div>;
  }
  if (model.versions.length === 0) {
    return (
      <div className="jp-snapshot-panel-empty">
        <div>暂无快照</div>
        <div className="jp-snapshot-panel-hint">点击工具栏「保存快照」按钮创建</div>
      </div>
    );
  }
  return (
    <ul className="jp-snapshot-panel-list">
      {model.versions.map(v => (
        <li key={v.id} className="jp-snapshot-panel-item">
          <div className="jp-snapshot-panel-item-header">
            <span className="jp-snapshot-panel-name" title={v.name}>
              {v.name}
            </span>
            <span className="jp-snapshot-panel-size">{formatSize(v.size)}</span>
          </div>
          {v.description ? (
            <div className="jp-snapshot-panel-desc">{v.description}</div>
          ) : null}
          <div className="jp-snapshot-panel-time">{formatTimestamp(v.timestamp)}</div>
          <div className="jp-snapshot-panel-actions">
            <button
              className="jp-snapshot-panel-button"
              onClick={async () => {
                const panel = tracker.currentWidget;
                if (!panel) {
                  return;
                }
                const notebookModel = panel.content.model;
                if (!notebookModel) {
                  return;
                }
                try {
                  const oldNb = (await getSnapshotContent(
                    serverSettings,
                    model.path,
                    v.id
                  )) as INotebook;
                  const newNb = notebookModel.toJSON() as unknown as INotebook;
                  onOpenDiff(newNb, oldNb, v.name);
                } catch (e) {
                  console.error('Diff failed', e);
                }
              }}
            >
              对比
            </button>
            <button
              className="jp-snapshot-panel-button"
              onClick={() => {
                void app.commands.execute(CommandIDs.restore, { id: v.id });
              }}
            >
              恢复
            </button>
          </div>
        </li>
      ))}
    </ul>
  );
};

export class SnapshotPanel extends ReactWidget {
  constructor(
    private readonly _props: PanelProps
  ) {
    super();
    this.addClass('jp-snapshot-panel');
  }

  render(): React.ReactElement {
    return <Panel {...this._props} />;
  }
}
