import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectSpread from "@babel/runtime/helpers/objectSpread";

/**
 * Web Input Component
 *
 */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Button, { propTypes as ButtonPropTypes } from '../button/Button';
import FormLabel from '../form-label/FormLabel';
import FormStatus from '../form-status/FormStatus';
import { isTrue, extendPropsWithContext, registerElement, validateDOMAttributes, processChildren, pickRenderProps, dispatchCustomElementEvent } from '../../shared/component-helper';
import { isIE11 } from '../../shared/helpers';
const renderProps = {
  on_change: null,
  on_submit: null,
  on_focus: null,
  on_blur: null,
  on_submit_focus: null,
  on_submit_blur: null
};
export const propTypes = {
  type: PropTypes.string,
  size: PropTypes.string,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  id: PropTypes.string,
  label: PropTypes.string,
  status: PropTypes.string,
  input_state: PropTypes.string,
  status_state: PropTypes.string,
  status_animation: PropTypes.string,
  autocomplete: PropTypes.oneOf(['on', 'off']),
  submit_button_title: PropTypes.string,
  placeholder: PropTypes.string,
  description: PropTypes.string,
  align: PropTypes.string,
  disabled: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  class: PropTypes.string,
  input_class: PropTypes.string,
  attributes: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  readOnly: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  // Submit button
  submit_button_variant: ButtonPropTypes.variant,
  submit_button_icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]),
  // React props
  className: PropTypes.string,
  inputElement: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
  children: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]),
  submitButton: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
  // Web Component props
  custom_element: PropTypes.object,
  custom_method: PropTypes.func,
  on_change: PropTypes.func,
  on_submit: PropTypes.func,
  on_focus: PropTypes.func,
  on_blur: PropTypes.func,
  on_submit_focus: PropTypes.func,
  on_submit_blur: PropTypes.func
};
export const defaultProps = _objectSpread({
  type: 'text',
  size: null,
  value: null,
  id: null,
  label: null,
  status: null,
  input_state: null,
  status_state: 'error',
  status_animation: null,
  autocomplete: 'off',
  placeholder: null,
  description: null,
  align: null,
  disabled: null,
  input_class: null,
  class: null,
  attributes: null,
  readOnly: false,
  // Submit button
  submit_button_title: null,
  submit_button_variant: 'secondary',
  submit_button_icon: 'search',
  // React props
  className: null,
  inputElement: null,
  children: null,
  submitButton: null,
  // Web Component props
  custom_element: null,
  custom_method: null
}, renderProps);
/**
 * The input component is an umbrella component for all inputs which share the same style as the classic `text` input field. Radio buttons and other form elements are not included here.
 */

export default class Input extends PureComponent {
  static enableWebComponent() {
    registerElement(Input.tagName, Input, defaultProps);
  }

  static getDerivedStateFromProps(props, state) {
    const value = Input.getValue(props);

    if (state._listenForPropChanges && value !== null && value !== state.value) {
      state.value = value;
    }

    if (props.disabled) {
      state.inputState = 'disabled';
    }

    if (props.input_state) {
      state.inputState = props.input_state;
    }

    state._listenForPropChanges = true;
    return state;
  }

  static getValue(props) {
    if (props.value) return props.value;
    return processChildren(props);
  }

  constructor(props) {
    super(props);

    _defineProperty(this, "state", {
      inputState: 'virgin',
      value: null
    });

    _defineProperty(this, "onFocusHandler", event => {
      const {
        value
      } = event.target;
      this.setState({
        value,
        _listenForPropChanges: false,
        inputState: 'focus'
      });
      dispatchCustomElementEvent(this, 'on_focus', {
        value,
        event
      });
    });

    _defineProperty(this, "onBlurHandler", event => {
      const {
        value
      } = event.target;
      this.setState({
        value,
        _listenForPropChanges: false,
        inputState: String(value || '').length > 0 ? 'dirty' : 'initial'
      });
      dispatchCustomElementEvent(this, 'on_blur', {
        value,
        event
      });
    });

    _defineProperty(this, "onChangeHandler", event => {
      const {
        value
      } = event.target;
      this.setState({
        value,
        _listenForPropChanges: false
      });
      dispatchCustomElementEvent(this, 'on_change', {
        value,
        event
      });
    });

    _defineProperty(this, "onKeyDownHandler", event => {
      if (event.key === 'Enter') {
        const {
          value
        } = event.target;
        dispatchCustomElementEvent(this, 'on_submit', {
          value,
          event
        });
      }
    });

    this._ref = React.createRef();
    this._id = props.id || "dnb-input-".concat(Math.round(Math.random() * 999)); // cause we need an id anyway
    // pass along all props we wish to have as params

    this.renderProps = pickRenderProps(props, renderProps); // make sure we dont trigger getDerivedStateFromProps on startup

    this.state._listenForPropChanges = true;
    this.state.value = Input.getValue(props);

    if (props.input_state) {
      this.state.inputState = props.input_state;
    }
  }

  render() {
    // consume the formRow context
    const props = this.context.formRow ? // use only the props from context, who are available here anyway
    extendPropsWithContext(this.props, this.context.formRow) : this.props;

    const {
      type,
      size,
      label,
      status,
      status_state,
      status_animation,
      disabled,
      placeholder,
      description,
      align,
      input_class,
      submit_button_title,
      submit_button_variant,
      submit_button_icon,
      submitButton,
      autocomplete,
      readOnly,
      class: _className,
      className,
      id: _id,
      //eslint-disable-line
      children,
      //eslint-disable-line
      value: _value,
      //eslint-disable-line
      on_submit,
      //eslint-disable-line
      inputElement: _inputElement
    } = props,
          attributes = _objectWithoutProperties(props, ["type", "size", "label", "status", "status_state", "status_animation", "disabled", "placeholder", "description", "align", "input_class", "submit_button_title", "submit_button_variant", "submit_button_icon", "submitButton", "autocomplete", "readOnly", "class", "className", "id", "children", "value", "on_submit", "inputElement"]);

    const {
      value,
      inputState
    } = this.state;
    const id = this._id;
    const showStatus = status && status !== 'error';
    const hasSubmitButton = submitButton || type === 'search';
    const classes = classnames('dnb-input', "dnb-input--".concat(type), //type_modifier
    size && "dnb-input--".concat(size), hasSubmitButton && 'dnb-input--has-submit-button', align && "dnb-input__align--".concat(align), showStatus && 'dnb-input__form-status', status && "dnb-input__status--".concat(status_state), _className, className);

    let _this$renderProps = this.renderProps,
        {
      inputElement: InputElement
    } = _this$renderProps,
        renderProps = _objectWithoutProperties(_this$renderProps, ["inputElement"]);

    const inputParams = _objectSpread({}, renderProps, {
      className: classnames('dnb-input__input', input_class),
      autoComplete: autocomplete,
      value: value || '',
      type,
      id,
      disabled,
      name: id
    }, attributes, {
      onChange: this.onChangeHandler,
      onKeyDown: this.onKeyDownHandler,
      onFocus: this.onFocusHandler,
      onBlur: this.onBlurHandler // we may considder using: aria-details

    });

    if (showStatus) {
      inputParams['aria-describedby'] = id + '-status';
    } else if (description) {
      inputParams['aria-describedby'] = id + '-description';
    }

    if (type === 'search') {
      inputParams.autoComplete = 'off';
    }

    if (readOnly) {
      inputParams['aria-readonly'] = inputParams.readOnly = true;
    }

    if (label) {
      inputParams['aria-labelledby'] = id + '-label';
    }

    const shellParams = {
      'data-input-state': inputState,
      'data-has-content': String(value || '').length > 0 ? 'true' : 'false'
    };

    if (disabled) {
      shellParams['aria-disabled'] = true;
    } // also used for code markup simulation


    validateDOMAttributes(this.props, inputParams);
    validateDOMAttributes(null, shellParams);

    if (InputElement && typeof InputElement === 'function') {
      InputElement = InputElement(inputParams, this._ref);
    } else if (!InputElement && _inputElement) {
      InputElement = _inputElement;
    }

    return React.createElement(React.Fragment, null, label && React.createElement(FormLabel, {
      id: id + '-label',
      for_id: id,
      text: label,
      disabled: disabled
    }), React.createElement("span", {
      className: classes
    }, React.createElement("span", _extends({
      className: "dnb-input__shell"
    }, shellParams), InputElement || React.createElement("input", _extends({
      ref: this._ref
    }, inputParams)), placeholder && !isIE11 && React.createElement("span", {
      "aria-hidden": true,
      className: classnames('dnb-input__placeholder', align ? "dnb-input__align--".concat(align) : null)
    }, placeholder)), hasSubmitButton && (submitButton ? submitButton : React.createElement(SubmitButton, _extends({}, attributes, {
      value: inputParams.value,
      icon: submit_button_icon,
      title: submit_button_title,
      variant: submit_button_variant,
      disabled: disabled
    }))), showStatus && React.createElement(FormStatus, {
      text: status,
      status: status_state,
      text_id: id + '-status' // used for "aria-describedby"
      ,
      animation: status_animation
    })), this.props.description && React.createElement("span", {
      className: "dnb-input__description",
      id: id + '-description' // used for "aria-describedby"

    }, this.props.description));
  }

}

_defineProperty(Input, "tagName", 'dnb-input');

_defineProperty(Input, "defaultProps", defaultProps);

_defineProperty(Input, "renderProps", renderProps);

Input.propTypes = process.env.NODE_ENV !== "production" ? propTypes : {};

class SubmitButton extends PureComponent {
  constructor() {
    super(...arguments);

    _defineProperty(this, "state", {
      focusState: 'virgin'
    });

    _defineProperty(this, "onFocusHandler", event => {
      const value = this.props.value;
      this.setState({
        focusState: 'focus'
      });
      dispatchCustomElementEvent(this, 'on_submit_focus', {
        value,
        event
      });
    });

    _defineProperty(this, "onBlurHandler", event => {
      const value = this.props.value;
      this.setState({
        focusState: 'dirty'
      });
      dispatchCustomElementEvent(this, 'on_submit_blur', {
        value,
        event
      });
    });

    _defineProperty(this, "onSubmitHandler", event => {
      const value = this.props.value;
      dispatchCustomElementEvent(this, 'on_submit', {
        value,
        event
      });
    });
  }

  render() {
    const _this$props = this.props,
          {
      id,
      title,
      disabled,
      variant,
      icon,
      icon_size
    } = _this$props,
          rest = _objectWithoutProperties(_this$props, ["id", "title", "disabled", "variant", "icon", "icon_size"]);

    const params = _objectSpread({
      id,
      type: 'submit',
      title,
      disabled: isTrue(disabled)
    }, rest); // also used for code markup simulation


    validateDOMAttributes(this.props, params);
    return React.createElement("span", {
      className: "dnb-input__submit-button",
      "data-input-state": this.state.focusState
    }, React.createElement(Button, _extends({
      className: "dnb-input__submit-button__button",
      variant: variant,
      icon: icon,
      size: icon_size,
      onClick: this.onSubmitHandler,
      onFocus: this.onFocusHandler,
      onBlur: this.onBlurHandler
    }, params)));
  }

}

_defineProperty(SubmitButton, "defaultProps", {
  id: null,
  value: null,
  title: null,
  disabled: false,
  variant: 'secondary',
  icon: 'search',
  icon_size: 'medium',
  // Web Component props
  on_submit: null,
  on_submit_focus: null,
  on_submit_blur: null
});

SubmitButton.propTypes = process.env.NODE_ENV !== "production" ? {
  id: PropTypes.string,
  value: PropTypes.string,
  title: PropTypes.string,
  variant: ButtonPropTypes.variant,
  disabled: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]),
  icon_size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  // Web Component props
  on_submit: PropTypes.func,
  on_submit_focus: PropTypes.func,
  on_submit_blur: PropTypes.func
} : {};
export { SubmitButton };