import PropTypes from “prop-types” import PropTypesExact from “prop-types-exact” import React from “react”

const inflection = require(“inflection”)

export default class BootstrapSelect extends React.Component {

static propTypes = PropTypesExact({
  attribute: PropTypes.string,
  children: PropTypes.node,
  className: PropTypes.string,
  "data-controller": PropTypes.string,
  defaultValue: PropTypes.oneOfType([PropTypes.array, PropTypes.number, PropTypes.string]),
  description: PropTypes.node,
  disabled: PropTypes.bool,
  id: PropTypes.string,
  includeBlank: PropTypes.bool,
  hideSearch: PropTypes.bool,
  hint: PropTypes.node,
  hintBottom: PropTypes.node,
  label: PropTypes.node,
  labelContainerClassName: PropTypes.string,
  model: PropTypes.object,
  multiple: PropTypes.bool,
  name: PropTypes.string,
  placeholder: PropTypes.string,
  onChange: PropTypes.func,
  options: PropTypes.array,
  select2: PropTypes.bool,
  wrapperClassName: PropTypes.string,
})

componentDidMount() {
  if (this.props.select2 && this.props.onChange)
    $(this.refs.select).on("change", this.props.onChange)

  // Set default value to nothing when multiple
  if (this.props.select2 && this.props.multiple && !this.inputDefaultValue())
    $(this.refs.select).val("")
}

componentWillUnmount() {
  if (this.props.select2 && this.props.onChange)
    $(this.refs.select).off("change", this.props.onChange)
}

render() {
  return (
    <div className={this.wrapperClassName()}>
      {this.label() &&
        <div className={this.props.labelContainerClassName ? this.props.labelContainerClassName : null}>
          <label className={this.labelClassName()} htmlFor={this.inputId()}>
            {this.label()}
          </label>
        </div>
      }
      {this.props.description &&
        <div className="mb-4">
          {this.props.description}
        </div>
      }
      {this.props.hint &&
        <span className="form-text text-muted font-smoothing font-xs">
          {this.props.hint}
        </span>
      }
      <select
        data-controller={this.dataController()}
        data-hide-search={this.props.hideSearch}
        data-placeholder={this.props.placeholder}
        defaultValue={this.inputDefaultValue()}
        className={`form-control ${this.props.className}`}
        disabled={this.props.disabled}
        id={this.inputId()}
        multiple={this.props.multiple}
        name={this.inputName()}
        onChange={this.props.onChange}
        ref="select"
        >
        {this.includeBlank() &&
          <option />
        }
        {this.props.options && this.props.options.map(option => (
          <option key={`select-option-${option[1]}`} value={option[1]}>{option[0]}</option>
        ))}
        {this.props.children}
      </select>
      {this.props.hintBottom &&
        <span className="form-text text-muted font-smoothing font-xs">
          {this.props.hintBottom}
        </span>
      }
    </div>
  )
}

dataController() {
  if ("data-controller" in this.props) {
    return this.props["data-controller"]
  } else if (this.props.select2) {
    return "select2--default"
  }
}

includeBlank() {
  if (this.props.includeBlank || (this.props.placeholder && !this.props.multiple)) {
    return true
  } else {
    return false
  }
}

inputDefaultValue() {
  if ("defaultValue" in this.props) {
    return this.props.defaultValue
  } else if (this.props.selected) {
    return this.props.selected
  } else if (this.props.model) {
    if (!this.props.model[this.props.attribute])
      throw new Error(`No attribute by that name: ${this.props.attribute}`)

    return this.props.model[this.props.attribute]()
  }
}

inputId() {
  if ("id" in this.props) {
    return this.props.id
  } else if (this.props.model) {
    return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
  }
}

inputName() {
  if ("name" in this.props) {
    return this.props.name
  } else if (this.props.model) {
    return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
  }
}

label() {
  if ("label" in this.props) {
    return this.props.label
  } else if (this.props.model) {
    let attributeMethodName = inflection.camelize(this.props.attribute.replace(/_id$/, ""), true)
    return this.props.model.modelClass().humanAttributeName(attributeMethodName)
  }
}

labelClassName() {
  let classNames = ["form-group-label"]

  if (this.props.labelClassName)
    classNames.push(this.props.labelClassName)

  return classNames.join(" ")
}

wrapperClassName() {
  let classNames = ["form-group", "component-bootstrap-select"]

  if (this.props.wrapperClassName)
    classNames.push(this.props.wrapperClassName)

  return classNames.join(" ")
}

}