import { IMedia, getClassNames, withSchema } from '@websolutespa/bom-core';
import { RefObject, forwardRef } from 'react';
import styled, { css } from 'styled-components';
import { UIComponentWithRef, UIStyledComponentProps } from '../../components/types';
import { getAspectResponsive, getCssResponsive } from '../../components/utils';
import { useMediaGalleryContext } from '../media-gallery/media-gallery-context';
import { MediaSize } from './media-image';
import { MediaItems } from './media-items';

export type MediaInfoProps = UIStyledComponentProps;

const StyledMediaInfo = styled.div`
  position: absolute;
  display: flex;
  flex-direction: column;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  color: var(--color-neutral-100);

  ${props => getCssResponsive(props)}
`;

const MediaInfo = ({ children, className, ...props }: MediaInfoProps) => {
  const classNames = getClassNames(className, 'media-info');
  return (<StyledMediaInfo className={classNames} {...props}>{children}</StyledMediaInfo>);
};

type Props = {
  size?: MediaSize;
  circle?: boolean;
  rounded?: boolean;
  overlay?: boolean | number;
  eager?: boolean;
  alt?: string;
  title?: string;
  informative?: boolean;
  item?: IMedia | IMedia[];
  onLoaded?: (ref: RefObject<HTMLImageElement | HTMLVideoElement>) => void;
  canLoad?: boolean;
};

export type MediaProps = UIStyledComponentProps<Props>;

export type MediaComponent<C extends React.ElementType = 'div'> = UIComponentWithRef<C, Props>;

const StyledMedia = styled.div<MediaProps>`
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  ${props => getCssResponsive(props)}

  &>:not(.media-info) {
    width: 100%;
    height: 100%;
  }

  &>.image:not(.image-svg),
  &>video,
  &>.video {
    object-fit: cover;
    background: transparent;
  }

  &>svg {
    height: 100%;
  }

  &.media--gallery {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    cursor: pointer;

    &>:not(.media-info) {
      transition: ease-in-out 200ms;
      transition-property: transform, opacity;
    }

    &:hover {
      &>:not(.media-info) {
        transform: scale(1.05);
      }
    }
  }

  ${props => props.circle ? css`
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 50%;
    &>* {
      top: 0;
      left: 0;
      height: 100%;
    }
  ` : ''}

  ${props => props.rounded ? css`
    overflow: hidden;
    border-radius: var(--border-radius);
  ` : ''}

  ${props => getAspectResponsive(props, props.circle ? { aspectRatio: 1 } : undefined)}

  ${props => props.overlay ? css`
    position: relative;

    &:after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      ${getOverlayCss(props.overlay)}
    }
  ` : ''}
`;

function getOverlayCss(overlay: boolean | number): string {
  return (
    typeof overlay === 'number' ?
      `background: rgba(0,0,0,${overlay});` :
      'background: rgba(0,0,0,0.4);'
  );
  // 'background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.1) 15.9%, rgba(0, 0, 0, 0) 41.67%, rgba(0, 0, 0, 0.1) 61.79%, rgba(0, 0, 0, 0.6) 100%);'
}

const MediaBase: MediaComponent = forwardRef(({
  children,
  item,
  className,
  width,
  height,
  size,
  eager,
  alt,
  title,
  informative,
  onClick,
  onLoaded,
  canLoad,
  as = 'div',
  ...props
}, ref) => {
  const { id, open } = useMediaGalleryContext();
  const classNames = getClassNames(className, 'media', { 'media--gallery': id });
  const style: { width?: string, height?: string } = {};
  if (typeof width === 'string') {
    style.width = width;
  }
  if (typeof height === 'string') {
    style.height = height;
  }
  return (
    <StyledMedia className={classNames} ref={ref} as={as} {...props} {...style}>
      {children ? (
        children
      ) : (
        item && <MediaItems item={item} options={{
          width,
          height,
          aspectRatio: props.aspectRatio,
          aspectRatioSm: props.aspectRatioSm,
          aspectRatioMd: props.aspectRatioMd,
          aspectRatioLg: props.aspectRatioLg,
          aspectRatioXl: props.aspectRatioXl,
          galleryId: id,
          size,
          eager,
          alt,
          title,
          informative,
          open,
          onLoaded,
          canLoad,
        }} />
      )}
    </StyledMedia>
  );
});

MediaBase.displayName = 'Media';

export const Media = withSchema(
  MediaBase,
  {
    Info: MediaInfo,
  });
