import classNames from 'classnames';
import extend from 'extend';
import React, { PropTypes } from 'react';

import KdPopover from '../KdPopover';
import { dispatchCustomEvent } from '../../utils';
import { ASC, DESC } from '../../constants';

const defaultProps = {
  isChickletNone: false,
  isLoading: false,
  hasMainSelector: false,
  autocompleteVisible: false,
  draggable: false,
  direction: ASC,
  chicklets: {
    sortable: false,
    visible: true,
    fullwidth: false,
    buttons: {
      ascDesc: { visible: false },
      info: { visible: false },
      clearInput: { visible: false },
    },
    events: {},
    clearAll: { visible: false },
  },
};

const propTypes = {
  theme: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.func,
  ]).isRequired,
  onRemove: PropTypes.func,
  label: PropTypes.string,
  value: PropTypes.oneOfType([
    PropTypes.string, PropTypes.array, PropTypes.number, PropTypes.object,
  ]),

  isChickletNone: PropTypes.bool,
  hasMainSelector: PropTypes.bool,
  isLoading: PropTypes.bool,
  autocompleteVisible: PropTypes.bool,
  toggleItemDirection: PropTypes.func,
  direction: PropTypes.string,
  api: PropTypes.shape({
    url: PropTypes.string.isRequired,
    key: PropTypes.string.isRequired,
  }),
  kdFilterModel: PropTypes.object,
  item: PropTypes.object,
  draggable: PropTypes.bool,
  category: PropTypes.string,
  chicklets: PropTypes.shape({
    sortable: PropTypes.bool,
    visible: PropTypes.bool,
    fullwidth: PropTypes.bool,
    prefix: PropTypes.string,

    buttons: PropTypes.shape({
      ascDesc: PropTypes.shape({ visible: PropTypes.bool }),
      info: PropTypes.shape({ visible: PropTypes.bool }),
      clearInput: PropTypes.shape({ visible: PropTypes.bool }),
    }),

    events: PropTypes.shape({
      onClick: PropTypes.func,
      onClose: PropTypes.func,
    }),

    clearAll: PropTypes.shape({
      visible: PropTypes.bool,
      onClick: PropTypes.func,
    }),
  }),
};

class KdItemSelected extends React.Component {
  constructor(props) {
    super(props);

    this.chicklets = extend(true, {}, defaultProps.chicklets, this.props.chicklets);
    this.handleRemove = this.handleRemove.bind(this);
    this.handleOnClick = this.handleOnClick.bind(this);
    this.renderLabel = this.renderLabel.bind(this);
    this.renderItemWithIcon = this.renderItemWithIcon.bind(this);
    this.renderItem = this.renderItem.bind(this);
    this.togglePopover = this.togglePopover.bind(this);
    this.toggleItemDirection = this.toggleItemDirection.bind(this);

    this.state = { isPopoverOpen: false, direction: this.props.direction };
  }

  togglePopover() {
    this.setState({ isPopoverOpen: !this.state.isPopoverOpen });
  }

  toggleItemDirection() {
    const { value, toggleItemDirection } = this.props;
    this.setState({ direction: this.state.direction === ASC ? DESC : ASC });

    if (toggleItemDirection) {
      toggleItemDirection(value);
    }
  }

  renderInfoButton() {
    const { label, api, kdFilterModel, theme } = this.props;

    if (this.chicklets.buttons.info.visible) {
      return (
        <div
          className={
            classNames(
              'c-kd-item-selected__info-button',
              theme['c-kd-item-selected__info-button'],
            )
          }
          onClick={this.togglePopover}
        >
          {
            this.state.isPopoverOpen &&
              <KdPopover
                theme={theme}
                onRemove={this.togglePopover}
                {...{ label, api, kdFilterModel }}
              />
          }
        </div>
      );
    }

    return null;
  }

  handleRemove() {
    const { onRemove, item, label, value, direction } = this.props;
    const data = item || { label, value, direction };

    onRemove && onRemove({ data });
    dispatchCustomEvent(
      this.rootElement,
      'kd:ui:SelectEntity:onChickletClose',
      { data }
    );
  }

  handleOnClick(event) {
    if (this.chicklets.events.onClick) {
      this.chicklets.events.onClick(event);
    }
  }

  renderLabel() {
    let formatedLabel = this.props.label;
    if (this.chicklets.prefix) {
      // NOTE: dangerouslySetInnerHTML throws an error with spaces inside span
      formatedLabel = <span dangerouslySetInnerHTML={{ __html: `${this.chicklets.prefix} ${this.props.label}` }} />;
    }
    return formatedLabel;
  }

  renderItemWithIcon() {
    const {
      hasMainSelector,
      isLoading,
      autocompleteVisible,
    } = this.props;

    const { buttons: { clearInput: { visible } } } = this.chicklets;
    const { theme } = this.props;

    if (visible) {
      return (
        <div
          ref={ref => this.rootElement = ref}
          onClick={this.handleRemove}
          className={
            classNames({
              'u-iconx-inner-text': !hasMainSelector && autocompleteVisible,
              'u-iconx-inner-text-below-selector': hasMainSelector && autocompleteVisible,
              'u-margin-right-medium': isLoading,
              [theme['u-iconx-inner-text']]: !hasMainSelector && autocompleteVisible,
              [theme['u-iconx-inner-text-below-selector']]: hasMainSelector && autocompleteVisible,
              [theme['u-margin-right-medium']]: isLoading,
            })
          }
        />
      );
    }

    return null;
  }

  renderArrow() {
    const { direction } = this.state;
    const { theme } = this.props;
    return (
      <span
        className={
          classNames({
            'c-kd-item-selected__arrow_up': direction === ASC,
            'c-kd-item-selected__arrow_down': direction === DESC,
            [theme['c-kd-item-selected__arrow_up']]: direction === ASC,
            [theme['c-kd-item-selected__arrow_down']]: direction === DESC,
          })}
        onClick={this.toggleItemDirection}
      />
    );
  }

  renderItem() {
    const { draggable, chicklets, theme, category = 'default' } = this.props;
    return (
      <div
        ref={ref => this.rootElement = ref}
        onClick={this.handleOnClick}
        className={
          classNames(
            `c-kd-item-selected c-kd-item-selected--${category}`,
            { 'c-kd-item-selected__fullwidth': draggable || chicklets.fullwidth },
            theme['c-kd-item-selected'],
            theme[`c-kd-item-selected--${category}`],
            { [theme['c-kd-item-selected__fullwidth']]: draggable || chicklets.fullwidth },
          )
        }
      >
        {chicklets.buttons.ascDesc.visible && this.renderArrow()}
        <span
          className={
            classNames(
              'o-remove',
              `o-remove--${category}`,
              theme['o-remove'],
              theme[`o-remove--${category}`],
            )
          }
          onClick={this.handleRemove}
        />
        {this.renderInfoButton()}
        <span className={classNames('c-kd-item-selected-text', theme['c-kd-item-selected-text'])}>
          {this.renderLabel()}
        </span>
      </div>
    );
  }

  render() {
    return this.props.isChickletNone ? this.renderItemWithIcon() : this.renderItem();
  }
}

KdItemSelected.propTypes = propTypes;
KdItemSelected.defaultProps = defaultProps;

export default KdItemSelected;
