import React from 'react';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
import { Box, Chip, Header, Icon, IconButton, Icons, Text, as } from 'folds';
import { useSaveFile } from '../../hooks/useSaveFile';
import * as css from './ImageViewer.css';
import { useZoom } from '../../hooks/useZoom';
import { usePan } from '../../hooks/usePan';
import { downloadMedia } from '../../utils/matrix';
import { MobileTouchTarget } from '../../styles/mobile.css';

export type ImageViewerProps = {
  alt: string;
  src: string;
  requestClose: () => void;
};

export const ImageViewer = as<'div', ImageViewerProps>(
  ({ className, alt, src, requestClose, ...props }, ref) => {
    const { t } = useTranslation();
    const saveFile = useSaveFile();
    const { zoom, zoomIn, zoomOut, setZoom } = useZoom(0.2);
    const { pan, cursor, onMouseDown, onTouchStart } = usePan(zoom !== 1);

    const handleDownload = async () => {
      const fileContent = await downloadMedia(src);
      saveFile(fileContent, alt);
    };

    return (
      <Box
        className={classNames(css.ImageViewer, className)}
        direction="Column"
        {...props}
        ref={ref}
      >
        <Header className={css.ImageViewerHeader} size="400">
          <Box grow="Yes" alignItems="Center" gap="200">
            <IconButton
              size="300"
              radii="300"
              className={MobileTouchTarget}
              onClick={requestClose}
              aria-label="Close"
            >
              <Icon size="50" src={Icons.ArrowLeft} />
            </IconButton>
            <Text size="T300" truncate>
              {alt}
            </Text>
          </Box>
          <Box shrink="No" alignItems="Center" gap="200">
            <IconButton
              variant={zoom < 1 ? 'Success' : 'SurfaceVariant'}
              outlined={zoom < 1}
              size="300"
              radii="Pill"
              className={MobileTouchTarget}
              onClick={zoomOut}
              aria-label="Zoom Out"
            >
              <Icon size="50" src={Icons.Minus} />
            </IconButton>
            <Chip
              variant="SurfaceVariant"
              radii="Pill"
              className={MobileTouchTarget}
              onClick={() => setZoom(zoom === 1 ? 2 : 1)}
            >
              <Text size="B300">{Math.round(zoom * 100)}%</Text>
            </Chip>
            <IconButton
              variant={zoom > 1 ? 'Success' : 'SurfaceVariant'}
              outlined={zoom > 1}
              size="300"
              radii="Pill"
              className={MobileTouchTarget}
              onClick={zoomIn}
              aria-label="Zoom In"
            >
              <Icon size="50" src={Icons.Plus} />
            </IconButton>
            <Chip
              variant="Primary"
              onClick={handleDownload}
              radii="300"
              className={MobileTouchTarget}
              before={<Icon size="50" src={Icons.Download} />}
            >
              <Text size="B300">{t('Organisms.ImageViewer.download')}</Text>
            </Chip>
          </Box>
        </Header>
        <Box
          grow="Yes"
          className={css.ImageViewerContent}
          justifyContent="Center"
          alignItems="Center"
          onWheel={(evt) => {
            if (evt.deltaY < 0) zoomIn();
            else if (evt.deltaY > 0) zoomOut();
          }}
        >
          <img
            className={css.ImageViewerImg}
            style={{
              cursor,
              // translate runs inside scale(), so divide by zoom to make a dragged
              // pixel move the image one screen pixel (1:1 with the cursor) rather
              // than `zoom` pixels.
              transform: `scale(${zoom}) translate(${pan.translateX / zoom}px, ${
                pan.translateY / zoom
              }px)`,
            }}
            src={src}
            alt={alt}
            onMouseDown={onMouseDown}
            onTouchStart={onTouchStart}
          />
        </Box>
      </Box>
    );
  },
);
