import * as React from 'react';
import { FC, useCallback, CSSProperties, Fragment } from 'react';
import { IMedia } from '../../../types';
import { Helpers } from '../../../services/helpers';
import { Thumbnail } from '../../Thumbnail';
import { useStore } from '../../../services/store';

type Mapping = Array<{ x: number; y: number; size: number }>;

const DESKTOP_NUMBER_OF_COLUMNS = 6;
const DESKTOP_NUMBER_OF_ROW = 3;
const MOBILE_NUMBER_OF_COLUMNS = 3;
const MOBILE_NUMBER_OF_ROW = 6;

const DESKTOP_MOSAIC_MAPPING: Mapping = [
  { x: 0, y: 0, size: 2 },
  { x: 2, y: 0, size: 1 },
  { x: 2, y: 1, size: 1 },
  { x: 0, y: 2, size: 1 },
  { x: 1, y: 2, size: 1 },
  { x: 2, y: 2, size: 1 },
  { x: 3, y: 0, size: 1 },
  { x: 4, y: 0, size: 1 },
  { x: 5, y: 0, size: 1 },
  { x: 3, y: 1, size: 2 },
  { x: 5, y: 1, size: 1 },
  { x: 5, y: 2, size: 1 },
];

const MOBILE_MOSAIC_MAPPING: Mapping = [
  { x: 0, y: 0, size: 2 },
  { x: 2, y: 0, size: 1 },
  { x: 2, y: 1, size: 1 },
  { x: 0, y: 2, size: 1 },
  { x: 1, y: 2, size: 1 },
  { x: 2, y: 2, size: 1 },
  { x: 0, y: 3, size: 1 },
  { x: 0, y: 4, size: 1 },
  { x: 0, y: 5, size: 1 },
  { x: 1, y: 3, size: 2 },
  { x: 1, y: 5, size: 1 },
  { x: 2, y: 5, size: 1 },
];

export const Mosaic: FC = () => {
  const store = useStore();

  const generateGrid = useCallback(
    (medias: IMedia[], mapping: Mapping, columns: number, rows: number) => {
      const gridStyle = {
        ...gridStyleTemplate,
        gridTemplateColumns: Helpers.createArray(columns)
          .map(() => `${100 / columns}%`)
          .join(' '),
        gridTemplateRows: Helpers.createArray(rows)
          .map(() => 'auto')
          .join(' '),
      };

      const thumbnails = medias.map((media, i) => {
        const { x, y, size } = mapping[i];
        const style: CSSProperties = {
          gridColumn: `${x + 1} / span ${size}`,
          gridRow: `${y + 1} / span ${size}`,
        };

        return (
          <div className={`${store.config.classPrefix}-item`} style={style} key={i}>
            <Thumbnail media={media} position={i} />
          </div>
        );
      });

      return (
        <Fragment>
          <div className={`${store.config.classPrefix}-grid`} style={gridStyle}>
            {thumbnails}
          </div>
          <br />
        </Fragment>
      );
    },
    [store.config.classPrefix],
  );

  const renderDesktop = useCallback(() => {
    const chunkSize = DESKTOP_MOSAIC_MAPPING.length;
    const mediaChunks = Helpers.chunkArray(store.data.content.medias, chunkSize);

    return mediaChunks.map((chunk, i) => (
      <Fragment key={i}>
        {generateGrid(
          chunk,
          DESKTOP_MOSAIC_MAPPING,
          DESKTOP_NUMBER_OF_COLUMNS,
          DESKTOP_NUMBER_OF_ROW,
        )}
      </Fragment>
    ));
  }, [store.data.content.medias, generateGrid]);

  const renderMobile = useCallback(() => {
    const chunkSize = MOBILE_MOSAIC_MAPPING.length;
    const mediaChunks = Helpers.chunkArray(store.data.content.medias, chunkSize);

    return mediaChunks.map((chunk, i) => (
      <Fragment key={i}>
        {generateGrid(chunk, MOBILE_MOSAIC_MAPPING, MOBILE_NUMBER_OF_COLUMNS, MOBILE_NUMBER_OF_ROW)}
      </Fragment>
    ));
  }, [store.data.content.medias, generateGrid]);

  if (!store.root) {
    return null;
  }

  return (
    <div className={`${store.config.classPrefix}-layout-mosaic`} style={mosaicStyle}>
      {!store.isMobile ? renderDesktop() : renderMobile()}
    </div>
  );
};

export default Mosaic;

const mosaicStyle: CSSProperties = {
  textAlign: 'center',
};

const gridStyleTemplate: CSSProperties = {
  display: 'inline-grid',
  width: '100%',
};
