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 ToggleButton Component
 *
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import keycode from 'keycode';
import { isTrue, registerElement, extendPropsWithContext, dispatchCustomElementEvent } from '../../shared/component-helper';
import Radio from '../radio/Radio';
import Checkbox from '../checkbox/Checkbox';
import Button from '../button/Button';
import FormLabel from '../form-label/FormLabel';
import FormStatus from '../form-status/FormStatus';
import ToggleButtonGroup from './ToggleButtonGroup';
import ToggleButtonGroupContext from './ToggleButtonGroupContext';
import Context from '../../shared/Context';
const renderProps = {
  on_change: null,
  on_state_update: null
};
export const propTypes = {
  text: PropTypes.string,
  label: PropTypes.string,
  label_position: PropTypes.oneOf(['left', 'right']),
  title: PropTypes.string,
  checked: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  variant: PropTypes.oneOf(['default', 'checkbox', 'radio']),
  left_component: PropTypes.node,
  disabled: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  id: PropTypes.string,
  // group: PropTypes.string,
  status: PropTypes.string,
  status_state: PropTypes.string,
  status_animation: PropTypes.string,
  value: PropTypes.string,
  icon: PropTypes.string,
  icon_position: PropTypes.string,
  attributes: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  readOnly: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  class: PropTypes.string,
  /// React props
  className: PropTypes.string,
  children: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  // Web Component props
  custom_element: PropTypes.object,
  custom_method: PropTypes.func,
  on_change: PropTypes.func,
  on_state_update: PropTypes.func
};
export const defaultProps = _objectSpread({
  text: null,
  label: null,
  label_position: 'left',
  title: null,
  checked: null,
  variant: null,
  left_component: null,
  disabled: null,
  id: null,
  // group: null,
  status: null,
  status_state: 'error',
  status_animation: null,
  value: '',
  icon: null,
  icon_position: 'right',
  attributes: null,
  readOnly: false,
  class: null,
  // React props
  className: null,
  children: null,
  // Web Component props
  custom_element: null,
  custom_method: null
}, renderProps);
/**
 * The toggle-button component is our enhancement of the classic toggle-button button.
 */

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

  static getDerivedStateFromProps(props, state) {
    if (state._listenForPropChanges) {
      state.checked = ToggleButton.parseChecked(props.checked);
    }

    state._listenForPropChanges = true;
    return state;
  }

  constructor(props, context) {
    super(props);

    _defineProperty(this, "onKeyDownHandler", event => {
      switch (keycode(event)) {
        case 'enter':
          this.onClickHandler(event);
          break;
      }
    });

    _defineProperty(this, "onKeyUpHandler", event => {
      switch (keycode(event)) {
        case 'enter':
          this.onClickHandler(event);
          break;
      }
    });

    _defineProperty(this, "onClickHandler", event => {
      if (isTrue(this.props.readOnly)) {
        return event.preventDefault && event.preventDefault();
      } // only select a value once


      if (!isTrue(this.context.multiselect) && this.props.value === this.context.value) {
        return;
      } // else we change the checked sstate


      const checked = !this.state.checked;
      this.setState({
        // reset the status state, because the user has mad an action
        // status_state: null,
        checked,
        _listenForPropChanges: false
      });
      this.callOnChange({
        checked
      });

      if (this._refButton.current && checked) {
        // simulate focus for firefox and safari
        // so we can get rid of the hover ring after click
        try {
          this._refButton.current._ref.current.focus();
        } catch (e) {
          console.log(e);
        }
      }
    });

    _defineProperty(this, "callOnChange", (_ref) => {
      let {
        checked
      } = _ref;
      const {
        // group,
        value
      } = this.props;

      if (this.context.onChange) {
        this.context.onChange({
          value
        });
      }

      dispatchCustomElementEvent(this, 'on_change', {
        // group,
        checked,
        value
      });
    });

    this._id = props.id || "dnb-toggle-button-".concat(Math.round(Math.random() * 999)); // cause we need an id anyway

    this._refButton = React.createRef();
    this.state = {
      _listenForPropChanges: true // set the startup checked values from context, if they exists

    };

    if (context.name && typeof props.value !== 'undefined') {
      if (typeof context.value !== 'undefined') {
        this.state.checked = context.value === props.value;
        this.state._listenForPropChanges = false;
      } else if (context.values && Array.isArray(context.values)) {
        this.state.checked = context.values.includes(props.value);
        this.state._listenForPropChanges = false; // make sure we update the context
        // with a possible custom set "checked" state
      } else if (ToggleButton.parseChecked(props.checked)) {
        if (context.setContext) {
          if (context.multiselect) {
            context.setContext(tmp => {
              return {
                values: // in case we have set before a new context (other component)
                // we fill combine theese arrays
                tmp && Array.isArray(tmp.values) ? [...tmp.values, props.value] : [props.value]
              };
            });
          } else {
            context.setContext({
              value: props.value
            });
          }
        }
      }
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (ToggleButton.parseChecked(this.props.checked) !== ToggleButton.parseChecked(nextProps.checked)) {
      const {
        checked
      } = nextState;
      dispatchCustomElementEvent(this, 'on_state_update', {
        checked
      });
    }

    return true;
  }

  render() {
    return React.createElement(Context.Consumer, null, (_ref2) => {
      let {
        formRow
      } = _ref2;
      // consume the formRow context
      let props = formRow ? // use only the props from context, who are available here anyway
      extendPropsWithContext(this.props, formRow) : this.props; // consume the toggleButton context

      props = this.context.name ? // use only the props from context, who are available here anyway
      extendPropsWithContext(this.props, this.context) : props;

      const {
        status,
        status_state,
        status_animation,
        label,
        label_position,
        text,
        title,
        readOnly,
        className,
        class: _className,
        disabled,
        variant,
        left_component,
        id: _id,
        // eslint-disable-line
        // group: _group, // eslint-disable-line
        value: _value,
        // eslint-disable-line
        checked: _checked,
        // eslint-disable-line
        attributes,
        // eslint-disable-line
        children,
        // eslint-disable-line
        on_change,
        // eslint-disable-line
        on_state_update,
        // eslint-disable-line
        custom_method,
        // eslint-disable-line
        custom_element
      } = props,
            rest = _objectWithoutProperties(props, ["status", "status_state", "status_animation", "label", "label_position", "text", "title", "readOnly", "className", "class", "disabled", "variant", "left_component", "id", "value", "checked", "attributes", "children", "on_change", "on_state_update", "custom_method", "custom_element"]);

      let {
        checked
      } = this.state;

      if (!isTrue(this.context.multiselect) && typeof this.context.value !== 'undefined') {
        checked = _value === this.context.value;
      }

      const id = this._id;
      const showStatus = status && status !== 'error';
      const classes = classnames('dnb-toggle-button', status && "dnb-toggle-button__status--".concat(status_state), checked && "dnb-toggle-button--checked", label && label_position && "dnb-toggle-button--label-position-".concat(label_position), className, _className);

      const buttonParams = _objectSpread({
        id,
        disabled,
        text: text,
        title: title,
        ['aria-pressed']: String(checked)
      }, rest);

      const componentParams = {
        checked,
        disabled,
        ['aria-hidden']: true,
        tabIndex: '-1'
      };

      if (status) {
        // do not send along the message, but only the status states
        if (status_state === 'info') {
          componentParams.status_state = 'info';
        } else {
          componentParams.status = 'error';
        }
      }

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

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

      let leftComponent = null;

      switch (variant) {
        case 'radio':
          leftComponent = React.createElement(Radio, _extends({
            id: "".concat(id, "-radio")
          }, componentParams));
          break;

        case 'checkbox':
          leftComponent = React.createElement(Checkbox, _extends({
            id: "".concat(id, "-checkbox")
          }, componentParams));
          break;

        case 'default':
        default:
          leftComponent = left_component;
          break;
      }

      return React.createElement(React.Fragment, null, React.createElement("span", {
        className: classes
      }, label && React.createElement(FormLabel, {
        id: id + '-label',
        for_id: id,
        text: label,
        disabled: disabled
      }), React.createElement("span", {
        className: "dnb-toggle-button__shell"
      }, React.createElement(Button, _extends({
        variant: "secondary",
        className: "dnb-toggle-button__button"
      }, buttonParams, {
        ref: this._refButton,
        onClick: this.onClickHandler,
        onKeyDown: this.onKeyDownHandler,
        onKeyUp: this.onKeyUpHandler
      }), leftComponent && React.createElement("span", {
        className: "dnb-toggle-button__component"
      }, leftComponent)))), showStatus && React.createElement(FormStatus, {
        text: status,
        status: status_state,
        text_id: id + '-status' // used for "aria-describedby"
        ,
        animation: status_animation
      }));
    });
  }

}

_defineProperty(ToggleButton, "tagName", 'dnb-toggle-button');

_defineProperty(ToggleButton, "defaultProps", defaultProps);

_defineProperty(ToggleButton, "renderProps", renderProps);

_defineProperty(ToggleButton, "contextType", ToggleButtonGroupContext);

_defineProperty(ToggleButton, "Group", ToggleButtonGroup);

_defineProperty(ToggleButton, "parseChecked", state => /true|on/.test(String(state)));

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