/* eslint-env browser */

import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { Manager, Reference, Popper } from 'react-popper';
import classnames from 'classnames';
import { ClickAwayListener } from '../../core/helpers/clickAwayListener/ClickAwayListener';
import { dropUnwantedProps, modifierCSS } from '../../helpers';
import { Icon } from '../../core/atoms/icon/Icon';
import { TechnologyBadge } from '../../core/atoms/technologyBadge/TechnologyBadge';
import { Badge } from '../../core/atoms/badge/Badge';
import { useMapInteractionContext } from '../mapInteraction/MapInteractionContext';
import { useDragContainerContext } from './PipelineDragContainer';

const propTypes = {
  children: PropTypes.node,
  /**
   * The component used for the root node.
   * Either a string to use a DOM element or a component.
   */
  tag: PropTypes.elementType,
  defaultClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
  defaultPlacement: PropTypes.string,
  className: PropTypes.string,
  category: PropTypes.string,
  name: PropTypes.string.isRequired,
  technology: PropTypes.string,
  technologyIcon: PropTypes.string,
  technologyIconUrl: PropTypes.string,
  message: PropTypes.node,
  isFocus: PropTypes.bool,
  onFocus: PropTypes.func,
  status: PropTypes.string,
  statusInfos: PropTypes.string,
  defaultOffset: PropTypes.shape({
    top: PropTypes.number,
    left: PropTypes.number,
  }),
  popperClassName: PropTypes.string,
  context: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
  version: PropTypes.string,
  autoClosePopper: PropTypes.bool,
};

const defaultProps = {
  children: '',
  tag: 'div',
  defaultClassName: 'sui-prj-pipeline-job',
  defaultPlacement: 'top',
  defaultOffset: { top: 0, left: 0 },
  className: '',
  category: '',
  technology: '',
  technologyIcon: '',
  technologyIconUrl: null,
  message: '',
  isFocus: false,
  onFocus: () => {},
  status: '',
  statusInfos: '',
  popperClassName: 'sui-prj-pipeline-job__popper',
  context: false,
  version: '',
  autoClosePopper: false,
};

export const PipelineJob = ({
  isFocus: isFocusProp,
  onFocus: onFocusProp,
  children,
  defaultPlacement,
  defaultOffset,
  popperClassName,
  autoClosePopper,
  tag: Tag,
  defaultClassName,
  className,
  category,
  name,
  technology,
  technologyIcon,
  technologyIconUrl,
  message,
  status,
  statusInfos,
  version,
  context,
  ...props
}) => {
  const { isDragging: isDraggingItems } = useDragContainerContext();
  const { isDragging: isDraggingMap, scale: scaleMap } = useMapInteractionContext();
  const [isFocus, setIsFocus] = useState(isFocusProp);
  const onFocusRef = useRef();
  onFocusRef.current = onFocusProp;

  const handleFocus = (val) => {
    setIsFocus(val);
    onFocusRef.current(val);
  };

  useEffect(() => {
    setIsFocus(isFocusProp);
  }, [isFocusProp]);

  useEffect(() => {
    handleFocus(false);
  }, [isDraggingItems, isDraggingMap, scaleMap]);

  const renderMainElement = (ref) => {
    const attibutes = dropUnwantedProps(props, ['isFocus', 'autoClosePopper']);

    const classes = classnames(
      defaultClassName,
      className,
      modifierCSS(status),
      {
        'as--focus': isFocus,
        'as--dragging': isDraggingItems,
      }
    );

    const getIconByStatus = (currentStatus) => {
      switch (currentStatus) {
      case 'awaiting':
        return <Icon name="clock" />;
      case 'requested':
      case 'queued':
        return (
          <svg className="sui-prj-slidein-animation" height="10" width="10">
            <circle cx="5" cy="5" r="2" />
          </svg>
        );
      case 'running':
        return <Icon name="spinner" className="sui-prj-spiner-animation" />;
      case 'succeeded':
        return <Icon name="fa-check" />;
      case 'failed':
        return <Icon name="fa-exclamation" />;
      case 'out_of_memory':
        return <Icon name="out-of-memory" />;
      case 'skipped':
        return <Icon name="fa-long-arrow-right" />;
      case 'stopping':
        return <Icon className="sui-prj-pulse-opacity-animation" name="fa-stop" />;
      case 'stopped':
        return <Icon name="fa-stop" />;
      case 'unknown':
        return <Icon name="fa-question" />;
      default:
        return (
          <svg height="10" width="10">
            <circle cx="5" cy="5" r="5" />
          </svg>
        );
      }
    };

    return (
      <Tag
        className={classes}
        {...attibutes}
        tabIndex="0"
        role="button"
        onKeyDown={(e) => { if (['Enter', ' '].includes(e.key)) { handleFocus(true); } }}
        onClick={() => handleFocus(true)}
      >
        { status && (
          <div className="sui-prj-pipeline-job__status">
            <i className="sui-prj-pipeline-job__anchor">
              { getIconByStatus(status) }
            </i>
            {status.replaceAll('_', ' ')}
            { statusInfos && (
              <div className="sui-prj-pipeline-job__info">{statusInfos}</div>
            )}
          </div>
        )}
        {message}
        <div className="sui-prj-pipeline-job__content" ref={ref || null}>
          <div className="sui-prj-pipeline-job__technology">
            <TechnologyBadge
              shadow="none"
              size="sm"
              icon={technologyIcon || technology}
              iconUrl={technologyIconUrl}
              label={technology}
            />
          </div>
          <div className="sui-prj-pipeline-job__details">
            <div className="sui-g-grid as--no-wrap as--gutter-xs">
              <div className="sui-g-grid__item">
                <div className="sui-prj-pipeline-job__name">
                  {name}
                </div>
              </div>
              <div className="sui-g-grid__item as--push">
                {version && (
                  <div className="sui-prj-pipeline-job__version">
                    <Badge position="end" size="xs">{version}</Badge>
                  </div>
                )}
              </div>
            </div>
            <div className="sui-prj-pipeline-job__type">
              {category}
            </div>
          </div>
        </div>
      </Tag>
    );
  };

  const formattedOffset = { offset: { offset: `${defaultOffset.left}, ${defaultOffset.top}` } };

  if (!children) {
    renderMainElement();
  }

  return (
    <Manager>
      <Reference>
        {({ ref }) => renderMainElement(ref)}
      </Reference>
      {isFocus
        ? ReactDOM.createPortal(
          <Popper placement={defaultPlacement} modifiers={formattedOffset}>
            {({ placement, ref, style }) => (
              <ClickAwayListener onClickOutside={() => handleFocus(false)} ref={ref}>
                <div
                  style={style}
                  data-placement={placement}
                  className={popperClassName}
                  onClick={autoClosePopper ? handleFocus(false) : null}
                  onKeyDown={autoClosePopper ? handleFocus(false) : null}
                  role="presentation"
                >
                  {children}
                </div>
              </ClickAwayListener>
            )}
          </Popper>,
          document.body
        )
        : ''}
    </Manager>
  );
};

PipelineJob.propTypes = propTypes;
PipelineJob.defaultProps = defaultProps;
