import { connect } from 'react-redux';
import React, { useEffect } from 'react';
import {
  galleryRotatePhoto,
  ImageGalleryState,
  ImageQueryResult,
  initImagesAction,
  nextPageAction,
  uniqueKey,
} from '../../reducers/imageGallery';
import Button from '@mui/material/Button';
import Lang from 'lang.js';
import trans from '../../translations';

const lang = new Lang({ messages: trans });

lang.setLocale((window as any).user_language || 'de');

const iconButtonStyle = {
  height: 38,
  minWidth: 42,
  padding: '6px 12px 6px 12px'
};

const greyTextButtonStyle = {
  backgroundColor: 'rgb(108,117,125)',
  color: 'white',
  '&:hover': {
    backgroundColor: 'rgb(91,98,104)',
  },
  padding: '6px 12px 6px 12px'
};

type Props = {
  initImages: () => void;
  getNextPage: () => void;
  rotatePhoto: (result: ImageQueryResult) => void;
  state: ImageGalleryState;
};

const Gallery: React.FC<Props> = (props) => {
  const { state, initImages, getNextPage, rotatePhoto } = props;
  // Upon mounting, initialize the gallery
  useEffect(() => {
    initImages();
  }, []);
  // Create a tile to be shown in the grid of images.
  const ImageTile: React.FC<ImageQueryResult> = (result) => {
    const fullResUrl = getFullResUrl(result);
    const thumbnailUrl = getThumbnailUrl(result);
    const extension = getFileExtension(result.pic_name);
    let imageEl;
    if (canEmbed(extension)) {
      imageEl = (
        <img
          className='image-tile-image'
          src={canThumbnail(extension) ? thumbnailUrl : fullResUrl}
        />
      );
    } else {
      imageEl = (
        <div className='image-tile-icon'>
          <img src={`/crmicons/${extension}.png`} />
        </div>
      );
    }
    return (
      <div className='image-tile' key={result.pic_id.toString()}>
        <div className='image-tile-image-container'>
          <a href={fullResUrl} target='_blank' rel='noopener noreferrer'>
            {imageEl}
          </a>
        </div>
        <div className='image-tile-label'>{result.pic_name}</div>
        <div className='image-tile-links'>
          <a
            href={`/comment/pdf/${result.erg_id}/`}
            target='_blank'
            rel='noopener noreferrer'
          >
            <Button variant='outlined' sx={iconButtonStyle}>🔍</Button>
          </a>
          {canThumbnail(extension) && (
            <a onClick={() => rotatePhoto(result)}>
              <Button variant='outlined' sx={iconButtonStyle}>
                <img src='/imgtasko/pic_rotate.png' />
              </Button>
            </a>
          )}
        </div>
      </div>
    );
  };

  switch (state.tag) {
    case 'not_loaded':
      return <h3>{lang.get('stats.notLoaded')}</h3>;
    case 'error':
      return <h3>{lang.get('stats.error')}</h3>;
    case 'loading':
      return <h3>{lang.get('stats.loading')}</h3>;
    case 'loaded':
      if (state.images.length === 0) {
        return <h3>{lang.get('stats.noData')}</h3>;
      } else {
        return (
          <div className='image-gallery'>
            <div className='image-grid'>
              {state.images.map((res) => (
                <ImageTile
                  {...res}
                  key={res.source.concat(res.pic_id.toString())}
                />
              ))}
            </div>
            ;
            <div className='load-more'>
              {state.loadingPage ? (
                <div>{lang.get('stats.loading')}</div>
              ) : state.lastPageReached ? (
                <div>{lang.get('stats.endOfResults')}</div>
              ) : (
                <Button onClick={getNextPage} sx={greyTextButtonStyle}>
                  {lang.get('stats.nextPage')}
                </Button>
              )}
            </div>
          </div>
        );
      }
  }

  function getFullResUrl(result: ImageQueryResult): string {
    switch (result.source) {
      case 'SOURCE_MBD_PIC':
        return `/image/${result.pic_id}`;
      case 'SOURCE_MBD_WEP':
        return `/api/file/${result.pic_name}`;
    }
  }
  function getThumbnailUrl(result: ImageQueryResult): string {
    let cacheHashtag = '';
    const cacheKey = uniqueKey(result);
    if (state.tag === 'loaded' && (cacheKey in state.reloadedImages)) {
      // We need to bypass the cache and force the image to be reloaded
      cacheHashtag = `${state.reloadedImages[cacheKey]}`;
    }
    switch (result.source) {
      case 'SOURCE_MBD_PIC':
        return `/thumbs_by_id/${result.pic_id}?cache=${cacheHashtag}`;
      case 'SOURCE_MBD_WEP':
        return `/thumbs_wep/${result.pic_id}?pktId=${result.pktid}&cache=${cacheHashtag}`;
    }
  }
};

// Return true iff the given file extension can be embedded in a <img> tab
function canEmbed(extension: string) {
  return ['jpg', 'jpeg', 'svg', 'png', 'apng', 'gif', 'bmp'].includes(
    extension
  );
}

/**
 * Return true iff the given file extension can be turned into a thumbnail on the server.
 * This is based on the limitations of php's 'imagecreatefromstring' function.
 * See https://www.php.net/manual/de/function.imagecreatefromstring.php
 */
function canThumbnail(extension: string) {
  return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'wbmp', 'gd2', 'webp'].includes(
    extension
  );
}

// Use regex to extract the file extension from a filename.
function getFileExtension(picName: string) {
  const match = picName.match(/\.[0-9a-z]+$/i);
  if (match === null || match.length === 0) {
    return '';
  }
  return match[0]
    .substring(1) // Remove the .
    .toLowerCase();
}

const mapStateToProps = (state /*, ownProps*/) => {
  return { state: state.imageGallery };
};

const mapDispatchToProps = (dispatch) => ({
  getNextPage: () => dispatch(nextPageAction()),
  rotatePhoto: (queryResult: ImageQueryResult) =>
    dispatch(galleryRotatePhoto(queryResult)),
  initImages: () => dispatch(initImagesAction()),
});

export default connect(mapStateToProps, mapDispatchToProps)(Gallery);
