import { IMedia, isMediaImage, isMediaVideo } from '@websolutespa/bom-core';
import { CSSProperties, RefObject, useMemo } from 'react';
import { MediaImage, MediaSize } from './media-image';
import { MediaVideo } from './media-video';

export type IMediaItemOptions = {
  size?: MediaSize;
  width?: CSSProperties['width'];
  height?: CSSProperties['height'];
  aspectRatio?: CSSProperties['aspectRatio'];
  aspectRatioSm?: CSSProperties['aspectRatio'];
  aspectRatioMd?: CSSProperties['aspectRatio'];
  aspectRatioLg?: CSSProperties['aspectRatio'];
  aspectRatioXl?: CSSProperties['aspectRatio'];
  eager?: boolean;
  galleryId?: string;
  alt?: string | undefined;
  title?: string | undefined;
  open?: (media: IMedia) => void;
  onLoaded?: (ref: RefObject<HTMLImageElement | HTMLVideoElement>) => void;
  canLoad?: boolean;
  informative?: boolean;
};

export type IMediaItemProps = {
  src?: string | undefined;
  mimeType?: string | undefined;
  alt?: string | undefined;
  title?: string | undefined;
  mediaWidth?: number;
  mediaHeight?: number;
  mediaFocalX?: number;
  mediaFocalY?: number;
  width?: CSSProperties['width'];
  height?: CSSProperties['height'];
  aspectRatio?: CSSProperties['aspectRatio'];
  aspectRatioSm?: CSSProperties['aspectRatio'];
  aspectRatioMd?: CSSProperties['aspectRatio'];
  aspectRatioLg?: CSSProperties['aspectRatio'];
  aspectRatioXl?: CSSProperties['aspectRatio'];
  size?: MediaSize;
  loading?: 'eager' | 'lazy';
  'data-gallery'?: string;
  onClick?: (event: React.MouseEvent) => void;
  onLoaded?: (ref: RefObject<HTMLImageElement | HTMLVideoElement>) => void;
  canLoad?: boolean;
  informative?: boolean;
};

export type IMediaItem = IMedia & {
  mediaWidth?: number;
  mediaHeight?: number;
  mediaFocalX?: number;
  mediaFocalY?: number;
  width?: CSSProperties['width'];
  height?: CSSProperties['height'];
  aspectRatio?: CSSProperties['aspectRatio'];
  aspectRatioSm?: CSSProperties['aspectRatio'];
  aspectRatioMd?: CSSProperties['aspectRatio'];
  aspectRatioLg?: CSSProperties['aspectRatio'];
  aspectRatioXl?: CSSProperties['aspectRatio'];
  onLoaded?: (ref: RefObject<HTMLImageElement | HTMLVideoElement>) => void;
  canLoad?: boolean;
};

export const MediaItem = ({
  item,
  options = {},
}: {
  item: IMedia,
  options?: IMediaItemOptions
}) => {
  const mediaItem: IMediaItem = useMemo(() => getMediaItem(item, options), [item, options]);
  const mediaItemProps: IMediaItemProps = useMemo(() => getMediaItemProps(mediaItem, options), [mediaItem, options]);
  return (isMediaVideo(mediaItem)) ?
    (
      <MediaVideo {...mediaItemProps} />
    ) : (
      <MediaImage {...mediaItemProps} />
    );
};

export const MediaItems = ({
  item,
  options = {},
}: {
  item: IMedia | IMedia[],
  options?: IMediaItemOptions
}) => {
  const items = (Array.isArray(item) ? item : [item]);
  return items.map((item, m) => (
    <MediaItem key={m} item={item} options={options} />
  ));
};

function getMediaItem(item: IMedia, options: IMediaItemOptions): IMediaItem {
  if (typeof item['media'] === 'object') {
    item = item['media'];
  }
  const mediaItem: IMediaItem = {
    type: item.type,
    src: item.src,
  };
  if (item.abstract) {
    mediaItem.abstract = item.abstract;
  }
  if (item.alt) {
    mediaItem.alt = item.alt;
  }
  if (item.mimeType) {
    mediaItem.mimeType = item.mimeType;
  }
  if (item.url) {
    mediaItem.src = item.url;
  }
  if (item.title) {
    mediaItem.title = item.title;
  }
  if (typeof item.width === 'number') {
    mediaItem.mediaWidth = item.width;
  }
  if (typeof item.height === 'number') {
    mediaItem.mediaHeight = item.height;
  }
  if (typeof item.focalX === 'number') {
    mediaItem.mediaFocalX = item.focalX;
  }
  if (typeof item.focalY === 'number') {
    mediaItem.mediaFocalY = item.focalY;
  }
  mediaItem.width = options.width;
  mediaItem.height = options.height;
  mediaItem.aspectRatio = options.aspectRatio;
  mediaItem.aspectRatioSm = options.aspectRatioSm;
  mediaItem.aspectRatioMd = options.aspectRatioMd;
  mediaItem.aspectRatioLg = options.aspectRatioLg;
  mediaItem.aspectRatioXl = options.aspectRatioXl;
  mediaItem.onLoaded = options.onLoaded;
  mediaItem.canLoad = options.canLoad;
  return mediaItem;
}

function getMediaItemProps(mediaItem: IMediaItem, options: IMediaItemOptions): IMediaItemProps {
  const { width, height, sizes, ...media } = mediaItem;
  const title: string | undefined = (media.title || options.title) as string | undefined;
  // console.log('getMediaItemProps', media.alt, options.alt);
  const alt: string | undefined = (media.alt || options.alt) as string | undefined;
  // const alt: string = (options.alt || '');
  const src: string = (media.src || media.url || '') as string;
  const mediaItemProps: IMediaItemProps = {
    src,
    title,
    alt,
    size: options.size,
    mimeType: media.mimeType,
    onLoaded: mediaItem.onLoaded,
    canLoad: mediaItem.canLoad,
  };
  const hasGallery = options.galleryId != null && typeof options.open === 'function';
  if (hasGallery) {
    mediaItemProps['data-gallery'] = JSON.stringify({ galleryId: options.galleryId, media });
    mediaItemProps.onClick = (event: React.MouseEvent) => {
      if (options.open) {
        options.open(media);
      }
    };
  }
  if (isMediaImage(media)) {
    mediaItemProps.mediaWidth = mediaItem.mediaWidth;
    mediaItemProps.mediaHeight = mediaItem.mediaHeight;
    mediaItemProps.mediaFocalX = mediaItem.mediaFocalX;
    mediaItemProps.mediaFocalY = mediaItem.mediaFocalY;
    mediaItemProps.width = options.width;
    mediaItemProps.height = options.height;
    mediaItemProps.aspectRatio = options.aspectRatio;
    mediaItemProps.aspectRatioSm = options.aspectRatioSm;
    mediaItemProps.aspectRatioMd = options.aspectRatioMd;
    mediaItemProps.aspectRatioLg = options.aspectRatioLg;
    mediaItemProps.aspectRatioXl = options.aspectRatioXl;
    mediaItemProps.informative = options.informative;
    if (options.eager) {
      mediaItemProps.loading = 'eager';
    }
  }
  return mediaItemProps;
}
