import { WindowService } from '@theia/core/lib/browser/window/window-service';
import { nls } from '@theia/core/lib/common';
import { shell } from 'electron';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown';
import { ProgressInfo, UpdateInfo } from '../../../common/protocol/ide-updater';
import ProgressBar from '../../components/ProgressBar';

export type IDEUpdaterComponentProps = {
  updateInfo: UpdateInfo;
  windowService: WindowService;
  downloadFinished?: boolean;
  downloadStarted?: boolean;
  progress?: ProgressInfo;
  error?: Error;
  onDownload: () => void;
  onClose: () => void;
  onSkipVersion: () => void;
  onCloseAndInstall: () => void;
};

export const IDEUpdaterComponent = ({
  updateInfo: { version, releaseNotes },
  downloadStarted = false,
  downloadFinished = false,
  windowService,
  progress,
  error,
  onDownload,
  onClose,
  onSkipVersion,
  onCloseAndInstall,
}: IDEUpdaterComponentProps): React.ReactElement => {
  const changelogDivRef = React.useRef() as React.MutableRefObject<
    HTMLDivElement
  >;
  React.useEffect(() => {
    if (!!releaseNotes) {
      let changelog: string;
      if (typeof releaseNotes === 'string') changelog = releaseNotes;
      else
        changelog = releaseNotes.reduce((acc, item) => {
          return item.note ? (acc += `${item.note}\n\n`) : acc;
        }, '');
      ReactDOM.render(
        <ReactMarkdown
          components={{
            a: ({ href, children, ...props }) => (
              <a onClick={() => href && shell.openExternal(href)} {...props}>
                {children}
              </a>
            ),
          }}
        >
          {changelog}
        </ReactMarkdown>,
        changelogDivRef.current
      );
    }
  }, [releaseNotes]);
  const closeButton = (
    <button onClick={onClose} type="button" className="theia-button secondary">
      {nls.localize('arduino/ide-updater/notNowButton', 'Not now')}
    </button>
  );

  const DownloadCompleted: () => React.ReactElement = () => (
    <div className="ide-updater-dialog--downloaded">
      <div>
        {nls.localize(
          'arduino/ide-updater/versionDownloaded',
          'Arduino IDE {0} has been downloaded.',
          version
        )}
      </div>
      <div>
        {nls.localize(
          'arduino/ide-updater/closeToInstallNotice',
          'Close the software and install the update on your machine.'
        )}
      </div>
      <div className="buttons-container">
        {closeButton}
        <button
          onClick={onCloseAndInstall}
          type="button"
          className="theia-button close-and-install"
        >
          {nls.localize(
            'arduino/ide-updater/closeAndInstallButton',
            'Close and Install'
          )}
        </button>
      </div>
    </div>
  );

  const DownloadStarted: () => React.ReactElement = () => (
    <div className="ide-updater-dialog--downloading">
      <div>
        {nls.localize(
          'arduino/ide-updater/downloadingNotice',
          'Downloading the latest version of the Arduino IDE.'
        )}
      </div>
      <ProgressBar percent={progress?.percent} showPercentage />
    </div>
  );

  const PreDownload: () => React.ReactElement = () => (
    <div className="ide-updater-dialog--pre-download">
      <div className="ide-updater-dialog--logo-container">
        <div className="ide-updater-dialog--logo"></div>
      </div>
      <div className="ide-updater-dialog--new-version-text dialogSection">
        <div className="dialogRow">
          <div className="bold">
            {nls.localize(
              'arduino/ide-updater/updateAvailable',
              'Update Available'
            )}
          </div>
        </div>
        <div className="dialogRow">
          {nls.localize(
            'arduino/ide-updater/newVersionAvailable',
            'A new version of Arduino IDE ({0}) is available for download.',
            version
          )}
        </div>
        {releaseNotes && (
          <div className="dialogRow">
            <div className="changelog-container" ref={changelogDivRef} />
          </div>
        )}
        <div className="buttons-container">
          <button
            onClick={onSkipVersion}
            type="button"
            className="theia-button secondary skip-version"
          >
            {nls.localize(
              'arduino/ide-updater/skipVersionButton',
              'Skip Version'
            )}
          </button>
          <div className="push"></div>
          {closeButton}
          <button
            onClick={onDownload}
            type="button"
            className="theia-button primary"
          >
            {nls.localize('arduino/ide-updater/downloadButton', 'Download')}
          </button>
        </div>
      </div>
    </div>
  );

  const onGoToDownloadClick = (
    event: React.SyntheticEvent<HTMLAnchorElement, Event>
  ) => {
    const { target } = event.nativeEvent;
    if (target instanceof HTMLAnchorElement) {
      event.nativeEvent.preventDefault();
      windowService.openNewWindow(target.href, { external: true });
      onClose();
    }
  };

  const GoToDownloadPage: () => React.ReactElement = () => (
    <div className="ide-updater-dialog--go-to-download-page">
      <div>
        {nls.localize(
          'arduino/ide-updater/goToDownloadPage',
          "An update for the Arduino IDE is available, but we're not able to download and install it automatically. Please go to the download page and download the latest version from there."
        )}
      </div>
      <div className="buttons-container">
        {closeButton}
        <a
          className="theia-button primary"
          href="https://www.arduino.cc/en/software#experimental-software"
          onClick={onGoToDownloadClick}
        >
          {nls.localize(
            'arduino/ide-updater/goToDownloadButton',
            'Go To Download'
          )}
        </a>
      </div>
    </div>
  );

  return (
    <div className="ide-updater-dialog--content">
      {!!error ? (
        <GoToDownloadPage />
      ) : downloadFinished ? (
        <DownloadCompleted />
      ) : downloadStarted ? (
        <DownloadStarted />
      ) : (
        <PreDownload />
      )}
    </div>
  );
};