import React, { Component } from 'react';
import classNames from 'classnames/bind';
import FormItemLabel, { FormItemLabelProps } from 'components/items/FormItemLabel';

import CustomIcon from 'components/items/CustomIcon';
import TextItem from 'components/items/TextItem';
import styleIdentifiers from './fieldWrapper.scss';

const styles = classNames.bind(styleIdentifiers);

export interface StateProps {}

export interface DispatchProps {}

export interface OwnProps {
  // say if the input has a value
  hasValue: boolean;
  // Additional className to add
  className: string;
  // Redux form input
  input: {};
  // Redux form meta
  meta: {};
  // Custom styling for the global field
  fieldWrapperClassName: string;
  fieldWrapperStyle: {};
  // Add border to the input
  withBorder: boolean;
  // Add border to the field value
  withValueBorder: boolean;
  // Custom styling for the content wrapper ( = content without icons)
  contentWrapperClassName: string;
  contentWrapperStyle: {};
  // Custom styling for the value
  valueClassName: string;
  valueStyle: {};
  // Center the value (not always applicable)
  centerValue: boolean;
  // Decrease padding for the types with-border and with-value-border
  small: boolean;
  // Remove all padding for types with-value-border
  noPadding: boolean;
  // effect if active/focused
  effect: boolean;
  // disabled or not
  disabled: boolean;
  // shadow style for field
  shadow: boolean;
  // Right icon
  iconRight: string;
  iconRightStyle: {};
  iconRightClassName: string;
  iconRightAction: Function;
  // Left icon
  iconLeft: string;
  iconLeftStyle: {};
  iconLeftClassName: string;
  iconLeftAction: Function;
  // Children to append
  children: any;
  // Other children to display outside of the value
  secondChildren: any;
  // Add class name on active effect
  effectActiveClassName: string;
  // Overwrite bar color for active - error - valid
  activeBarColor: string;
  errorBarColor: string;
  validBarColor: string;
  // add not string near label in italic
  notRequired: string;
  // tabIndex
  tabIndex: string;
  onFocus: Function;
  onBlur: Function;
  ignoreTouched: boolean;
  noShadow?: boolean;
  // for info message between label and input
  extraInfo?: string;
  extraInfoClassName?: string;
}

export type FieldWrapperProps = FormItemLabelProps & StateProps & DispatchProps & OwnProps;

interface FieldWrapperState {}

export default class FieldWrapper extends Component<FieldWrapperProps, FieldWrapperState> {
  iconLeft = (): JSX | boolean => {
    const { iconLeft, iconLeftAction, iconLeftStyle, iconLeftClassName } = this.props;

    if (!iconLeft) return false;

    return (
      iconLeft && (
        <div onClick={iconLeftAction} className={styles('icon-left', iconLeftAction && 'actionable', iconLeftClassName)} style={iconLeftStyle}>
          {typeof iconLeft === 'string' ? <CustomIcon icon={iconLeft} /> : iconLeft}
        </div>
      )
    );
  };

  iconRight = (): JSX => {
    const { iconRight, iconRightAction, iconRightStyle, iconRightClassName } = this.props;

    if (!iconRight) return false;

    return (
      iconRight && (
        <div onClick={iconRightAction} className={styles('icon-right', iconRightAction && 'actionable', iconRightClassName)} style={iconRightStyle}>
          {typeof iconRight === 'string' ? <CustomIcon icon={iconRight} /> : iconRight}
        </div>
      )
    );
  };

  renderLabel = (noFontSize): JSX => {
    const { extraInfo, extraInfoClassName } = this.props;

    return (
      <>
        <FormItemLabel {...this.props} noFontSize={noFontSize} className={styles(!noFontSize && 'label')} />
        {extraInfo && (
          <div className={styles('extra-info', extraInfoClassName)}>
            <TextItem path={extraInfo} />
          </div>
        )}
      </>
    );
  };

  renderContent = (borderType: string): JSX | boolean => {
    const {
      // value,
      contentWrapperClassName,
      contentWrapperStyle,
      statusBarClassName,
      disabledClassName,
      centerValue,
      valueClassName,
      valueStyle,
      children,
      secondChildren,
      // color
      errorBarColor,
      activeBarColor,
      validBarColor,
      disabled,
      effect,
      label,
      labelClassName,
      fieldsetClassName,
    } = this.props;

    if (borderType === 'with-border') {
      return (
        <>
          {effect && label && (
            <fieldset className={styles(fieldsetClassName)}>
              <legend className={styles(labelClassName)}>{this.renderLabel(true)}</legend>
            </fieldset>
          )}
          {this.iconLeft()}
          <div
            className={styles(
              'content-wrapper',
              centerValue && 'centered',
              contentWrapperClassName,
              disabled && 'disabled',
              disabled && disabledClassName,
            )}
            style={contentWrapperStyle}
          >
            {this.renderLabel()}
            <div className={styles('value', valueClassName)} style={valueStyle}>
              {children}
            </div>
            {secondChildren}
          </div>
          {this.iconRight()}
        </>
      );
    }
    if (borderType === 'with-value-border') {
      return (
        <>
          {this.renderLabel()}
          <div
            className={styles(
              'content-wrapper',
              contentWrapperClassName,
              centerValue && 'centered',
              disabled && 'disabled',
              disabled && disabledClassName,
            )}
            style={contentWrapperStyle}
          >
            {this.iconLeft()}
            <div className={styles('value', valueClassName)} style={valueStyle}>
              {children}
            </div>
            {this.iconRight()}
          </div>
          {secondChildren}
        </>
      );
    }
    if (borderType === 'with-border-bottom') {
      return (
        <>
          {this.iconLeft()}
          <div
            className={styles(
              'content-wrapper',
              contentWrapperClassName,
              centerValue && 'centered',
              disabled && 'disabled',
              disabled && disabledClassName,
            )}
            style={contentWrapperStyle}
          >
            {!effect && this.renderLabel()}
            <div className={styles('value', valueClassName)} style={valueStyle}>
              {effect && this.renderLabel()}
              {children}
            </div>
          </div>
          {this.iconRight()}
          {secondChildren}
          <div className={styles('valid-bar', statusBarClassName)} style={validBarColor && { backgroundColor: validBarColor }} />
          <div className={styles('error-bar', statusBarClassName)} style={errorBarColor && { backgroundColor: errorBarColor }} />
          <div className={styles('active-bar', statusBarClassName)} style={activeBarColor && { backgroundColor: activeBarColor }} />
        </>
      );
    }
    return false;
  };

  /**
   * Important consideration about structure
   *
   * 1. with border bottom (default)
   *
   * fieldWrapper => border bottom here
   *  iconLeft
   *  contentWrapper
   *    label
   *    value
   *  iconRight
   *
   * 2. with border
   *
   * fieldWrapper => border here
   *  iconLeft
   *  contentWrapper
   *    label
   *    value
   *  iconRight
   *
   * 3. with border bottom
   *
   * fieldWrapper
   *  label
   *  contentWrapper => border here
   *    iconLeft
   *    value
   *    iconRight
   */

  render(): JSX {
    const {
      input,
      hasValue,
      label,
      tabIndex,
      meta: { active, valid, error, touched },
      effect,
      withBorder,
      withValueBorder,
      small,
      noPadding,
      shadow,
      noShadow,
      // Styling
      // global
      fieldWrapperClassName,
      fieldWrapperStyle,
      iconLeft,
      iconRight,
      effectActiveClassName,
      beforeInputText,
      disabled,
      ignoreTouched,
      onClick,
      flex,
      isTextarea,
    } = this.props;

    let borderType;
    if (withBorder) {
      borderType = 'with-border';
    } else if (withValueBorder) borderType = 'with-value-border';
    else borderType = 'with-border-bottom';

    let inputHasValue = hasValue;
    if (inputHasValue === undefined) {
      inputHasValue = input && input.value;
    }

    return (
      <div
        className={styles(
          'FieldWrapper',
          borderType,
          noShadow && 'no-shadow',
          !label && 'no-label',
          small && 'small',
          noPadding && 'no-padding',
          shadow && 'shadow',
          // meta related
          active && 'active',
          touched && valid && 'valid',
          (touched || ignoreTouched) && error && !disabled && 'error',
          // effect
          effect && 'effect',
          effect && (active || inputHasValue) && 'effect-active',
          effect && (active || inputHasValue) && effectActiveClassName,
          iconLeft && 'with-left-icon',
          iconRight && 'with-right-icon',
          isTextarea && 'textarea',
          fieldWrapperClassName,
          beforeInputText && 'with-text-before-input',
          flex && 'flex',
        )}
        style={fieldWrapperStyle}
        tabIndex={tabIndex}
        onFocus={this.handleFocus}
        onBlur={this.handleBlur}
        onClick={onClick}
      >
        {this.renderContent(borderType)}
      </div>
    );
  }
}
