import { action } from '@ember/object';
import Component from '@glimmer/component';
import { A, isArray } from '@ember/array';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';

/**
  Bootstrap-style button group, that visually groups buttons, and optionally adds radio/checkbox like behaviour.
  See http://getbootstrap.com/components/#btn-groups

  Use as a block level component with any number of [Components.Button](Components.Button.html) components provided as
  a yielded pre-configured contextual component:

  ```handlebars
  <BsButtonGroup as |bg|>
    <bg.button>1</bg.button>
    <bg.button>2</bg.button>
    <bg.button>3</bg.button>
  </BsButtonGroup>
  ```

  ### Radio-like behaviour

  Use the `type` property set to "radio" to make the child buttons toggle like radio buttons, i.e. only one button can be active.
  Set the `value` property of the buttons to something meaningful. The `value` property of the button group will then reflect
  the value of the active button:

  ```handlebars
  <BsButtonGroup @value={{this.buttonGroupValue}} @type="radio" @onChange={{action (mut this.buttonGroupValue}} as |bg|>
    <bg.button @type="default" @value={{1}}>1</bg.button>
    <bg.button @type="default" @value={{2}}>2</bg.button>
    <bg.button @type="default" @value={{3}}>3</bg.button>
  </BsButtonGroup>

  You selected: {{this.buttonGroupValue}}!
  ```

  ### Checkbox-like behaviour

  Set `type` to "checkbox" to make any number of child buttons selectable. The `value` property will be an array
  of all the values of the active buttons:

  ```handlebars
  <BsButtonGroup @value={{this.buttonGroupValue}} @type="checkbox" @onChange={{action (mut this.buttonGroupValue}} as |bg|>
    <bg.button @type="default" @value={{1}}>1</bg.button>
    <bg.button @type="default" @value={{2}}>2</bg.button>
    <bg.button @type="default" @value={{3}}>3</bg.button>
  </BsButtonGroup>

  You selected:
  <ul>
    {{#each value in this.buttonGroupValue}}
      <li>{{value}}</li>
    {{/each}}
  </ul>
  ```

  *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.*

  @class ButtonGroup
  @namespace Components
  @extends Glimmer.Component
  @public
*/
@deprecateSubclassing
export default class ButtonGroup extends Component {
  /**
   * @property buttonComponent
   * @type {String}
   * @private
   */

  /**
   * Set to true for a vertically stacked button group, see http://getbootstrap.com/components/#btn-groups-vertical
   *
   * @property vertical
   * @type boolean
   * @default false
   * @public
   */

  /**
   * The type of the button group specifies how child buttons behave and how the `value` property will be computed:
   *
   * ### null
   * If `type` is not set (null), the button group will add no functionality besides Bootstrap styling
   *
   * ### radio
   * if `type` is set to "radio", the buttons will behave like radio buttons:
   * * the `value` property of the button group will reflect the `value` property of the active button
   * * thus only one button may be active
   *
   * ### checkbox
   * if `type` is set to "checkbox", the buttons will behave like checkboxes:
   * * any number of buttons may be active
   * * the `value` property of the button group will be an array containing the `value` properties of all active buttons
   *
   * @property type
   * @type string
   * @default null
   * @public
   */

  /**
   * The value of the button group, computed by its child buttons.
   * See the `type` property for how the value property is constructed.
   *
   * When you set the value, the corresponding buttons will be activated:
   * * use a single value for a radio button group to activate the button with the same value
   * * use an array of values for a checkbox button group to activate all the buttons with values contained in the array
   *
   * @property value
   * @type array
   * @public
   */

  /**
   * Property for size styling, set to 'lg', 'sm' or 'xs'
   *
   * Also see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/button-group/#sizing)
   *
   * @property size
   * @type String
   * @public
   */

  /**
   * This action is called whenever the button group's value should be changed because the user clicked a button.
   * You will receive the new value of the button group (based on the `type` property), which you should use to update the
   * `value` property.
   *
   * @event onChange
   * @param {*} value
   * @public
   */

  @action
  buttonPressed(pressedValue) {
    if (!this.args.onChange) {
      return;
    }
    let newValue;

    if (this.args.type === 'radio') {
      if (pressedValue === this.args.value) {
        return;
      }
      newValue = pressedValue;
    } else {
      if (!isArray(this.args.value)) {
        newValue = [pressedValue];
      } else {
        if (this.args.value.includes(pressedValue)) {
          newValue = this.args.value.filter((v) => v !== pressedValue);
        } else {
          newValue = [...this.args.value, pressedValue];
        }
      }

      // For compatibility we continue to return an EmberArray instance for now
      // @todo this should be changed for the next major release!
      newValue = A(newValue);
    }

    this.args.onChange(newValue);
  }
}