import React, { ReactElement } from 'react';
import css from '../../utils/css';

import Icon, { IconName, IconIntent } from '../Icon';

import unauthorized from './assets/image_403_HaRi.svg';
import notFound from './assets/image_404_HaRi.svg';
import serverError from './assets/image_500_HaRi.svg';
import underMaintenance from './assets/image_503_HaRi.svg';

import {
  ResultWrapper,
  ResultImg,
  TitleWrapper,
  SubTitleWrapper,
  ExtraWrapper,
  IconWrapper,
} from './StyledResult';

import { Either, left, right, match } from '../../fp/Either';
import { pipe } from '../../fp/function';

import { CommonProps } from '../common';

type ResultStatus =
  | 'success'
  | 'error'
  | 'info'
  | 'warning'
  | '404'
  | '403'
  | '500'
  | '503';
export interface ResultProps extends CommonProps {
  /**
   * Operating area, e.g. action buttons.
   */
  extra?: ReactElement | string;
  /**
   * Custom Icon to represent result type.
   */
  icon?: ReactElement;
  /**
   * Status to determine result style. This only gets effect if icon is not defined.
   */
  status?:
    | 'success'
    | 'error'
    | 'info'
    | 'warning'
    | '404'
    | '403'
    | '500'
    | '503';
  /**
   *  Subtitle text to show more details.
   */
  subTitle?: string | ReactElement;
  /**
   *  Main text to show result description.
   */
  title: string | ReactElement;
}

interface IconInfo {
  icon: IconName;
  intent: IconIntent;
}

const getEitherIconInfoOrImage = (
  status: ResultStatus
): Either<IconInfo, string> => {
  switch (status) {
    case 'success':
      return left({ icon: 'circle-ok', intent: 'success' });
    case 'error':
      return left({ icon: 'circle-cancel', intent: 'danger' });
    case 'info':
      return left({ icon: 'circle-info', intent: 'primary' });
    case 'warning':
      return left({ icon: 'circle-warning', intent: 'warning' });
    case '403':
      return right(unauthorized);
    case '404':
      return right(notFound);
    case '500':
      return right(serverError);
    case '503':
      return right(underMaintenance);
  }
};

const renderIcon = (status: ResultStatus): ReactElement => (
  <IconWrapper>
    {pipe(
      getEitherIconInfoOrImage(status),
      match(
        ({ icon, intent }: IconInfo) => <Icon icon={icon} intent={intent} />,
        image => <ResultImg src={image} alt="ExceptionSVG" />
      )
    )}
  </IconWrapper>
);

const Result = ({
  extra,
  subTitle,
  title,
  status = 'info',
  icon,
  id,
  className,
  style,
  sx = {},
  'data-test-id': dataTestId,
}: ResultProps): ReactElement => (
  <ResultWrapper
    id={id}
    className={className}
    style={{ ...style, ...css(sx) }}
    data-test-id={dataTestId}
  >
    {icon === undefined ? renderIcon(status) : icon}
    <TitleWrapper>{title}</TitleWrapper>
    {subTitle !== undefined && <SubTitleWrapper>{subTitle}</SubTitleWrapper>}
    {extra !== undefined && <ExtraWrapper>{extra}</ExtraWrapper>}
  </ResultWrapper>
);

export default Result;
