/* eslint react/prop-types: 0 */
import classNames from 'classnames';
import extend from 'extend';
import React from 'react';
import * as constants from '../../constants';

import {
  compose,
  mapProps,
  withState,
  withHandlers,
  setPropTypes,
  setDisplayName,
} from 'recompose';

import KdChickletsContainer from '../KdChickletsContainer';
import KdChickletsContainerDraggable from '../KdChickletsContainerDraggable';

import { dProps, pTypes } from './propTypes';
import { addItemHandler, behaviorHandler, errorHandler, optionHandler } from './handlers';
import { addChicklet, setChicklets, removeItem } from './chickletsHandler';
import {
  updateKdItemPosition,
} from './kdModelHelper';

const ItemContainerWrapper = WrappedComponent => props => {
  const {
    setErrors,
    setItems,
    clearErrors,
    wrapperState: { itemsState },
    setOption,
    theme,
    isChickletNone,
    chicklets,
    chicklets: {
      sortable,
    },
  } = props;

  const clearChicklets = (fireEvents = false) => {
    const { chicklets: { clearAll }, events } = props;
    const callback = () => {
      events && events.onChange && events.onChange({ data: 'reset' });
    };
    props.resetItems(callback);

    if (fireEvents && clearAll && clearAll.onClick) {
      clearAll.onClick();
    }
  };

  const addError = ({ errors }) => {
    setErrors(errors);
    if (isChickletNone()) {
      clearChicklets();
    }
  };

  const containerVisible = () => {
    const { chicklets: { container: { visible } } } = props;
    return visible;
  };

  const updateItemPosition = (value, position) => {
    const { kdFilterModel } = props;
    const itemIndex = itemsState.findIndex(elem => (elem.value === value));
    const item = itemsState.splice(itemIndex, 1);

    const selectedItems = kdFilterModel.getSortOrderModelValue();
    const valueItem = selectedItems.splice(itemIndex, 1);

    itemsState.splice(position, 0, item[0]);
    setItems(itemsState);

    selectedItems.splice(position, 0, valueItem[0]);
    updateKdItemPosition({ kdFilterModel, selectedItems });
  };

  const toggleItemDirection = (value) => {
    const { kdFilterModel, events } = props;
    const items = itemsState.map((item, index) => {
      if (item.value === value) {
        const direction = (item.direction === constants.ASC) ? constants.DESC : constants.ASC;
        const selectedItems = kdFilterModel.getSortOrderModelValue();
        selectedItems[index].direction = direction;
        kdFilterModel.setSelected(
          selectedItems.map(selectedItem => (
            {
              propertyName: selectedItem.propertyName,
              direction: selectedItem.direction,
            }
          ))
        );

        events &&
          events.onChange &&
          events.onChange({
            value: item.value,
            label: item.label,
            direction: item.direction,
          });
        return Object.assign({}, item, { direction });
      }
      return item;
    });

    setItems(items);
  };

  const changeOption = o => setOption(o);


  const lastInitialValue = () => {
    return (itemsState.length ? itemsState : props.selectedValuesInitial || []).slice(-1)[0];
  };

  const hasInitialValues = () => {
    return !!(props.selectedValuesInitial && props.selectedValuesInitial.length);
  };
  return (
    <div className={classNames('c-kd', theme['c-kd'])}>
      <WrappedComponent
        {...props}
        onItemAdded={props.addChicklet}
        onItemRemoved={props.removeItem}
        onOptionSelected={changeOption}
        onError={addError}
        clearErrors={clearErrors}
        isChickletNone={isChickletNone()}
        onClearChicklets={clearChicklets}
        onSetChicklets={props.setChicklets}
        emptyItems={!itemsState.length}
        lastInitialValue={lastInitialValue}
        hasInitialValues={hasInitialValues}
      />

      {
        !sortable &&
          containerVisible() &&
            <KdChickletsContainer
              theme={theme}
              items={itemsState}
              isChickletNone={isChickletNone()}
              labelHandler={props.chicklets.labelHandler}
            />
      }

      {
        sortable &&
          containerVisible() &&
            <KdChickletsContainerDraggable
              theme={theme}
              updateItemPosition={updateItemPosition}
              toggleItemDirection={toggleItemDirection}
              chicklets={chicklets}
              items={itemsState}
              labelHandler={props.chicklets.labelHandler}
            />
      }
    </div>
  );
};

const defaultPropMerge = props => extend(true, {}, dProps, props);

// Order matters here
const enhancer = compose(
  setDisplayName('WrapperComponent'),
  setPropTypes(pTypes),
  withState(
    'wrapperState',
    'setWrapperState',
    { itemsState: [], errorState: null, optionState: null }
  ),
  mapProps(props => ({
    ...props,
    ...defaultPropMerge(props),
  })),
  withHandlers({
    updateKdItemPosition,
    ...addItemHandler,
    ...behaviorHandler,
    ...errorHandler,
    ...optionHandler,
  }),
  withHandlers({ removeItem }),
  withHandlers({ addChicklet, setChicklets }),
  ItemContainerWrapper,
);

export default enhancer;

