/**
 * @license
 * Scale https://github.com/telekom/scale
 *
 * Copyright (c) 2021 Egor Kirpichev and contributors, Deutsche Telekom AG
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */
// ((input - min) * 100) / (max - min)
import { Component, h, State, Prop, Host, Event, Watch, Element, } from '@stencil/core';
import classNames from 'classnames';
import { emitEvent } from '../../utils/utils';
import statusNote from '../../utils/status-note';
let i = 0;
export class Slider {
  constructor() {
    /** t(optional) he minimal value of the slider */
    this.min = 0;
    /** (optional) the maximal value of the slider */
    this.max = 100;
    /** (optional) the step size to increase or decrease when dragging slider */
    this.step = 1;
    /** (optional) slider display value */
    this.showValue = true;
    /** (optional) slider value unit */
    this.unit = '%';
    /** (optional) number of decimal places */
    this.decimals = 0;
    /** (optional) disabled  */
    this.disabled = false;
    /** (optional) smaller track */
    this.trackSmall = false;
    /** (optional) larger thumb */
    this.thumbLarge = false;
    this.onButtonDown = () => {
      if (this.disabled) {
        return;
      }
      this.onDragStart();
      this.addGlobalListeners();
    };
    this.onKeyDown = (event) => {
      let steps = 0;
      if (['ArrowRight', 'ArrowLeft'].includes(event.key)) {
        steps = event.key === 'ArrowRight' ? this.step : -this.step;
      }
      if (['ArrowUp', 'ArrowDown'].includes(event.key)) {
        steps = event.key === 'ArrowUp' ? this.step * 10 : -this.step * 10;
      }
      this.setValue(this.value + steps);
    };
    this.onDragStart = () => {
      this.dragging = true;
      this.offsetLeft = this.sliderTrack.getBoundingClientRect().left;
    };
    this.onDragging = (event) => {
      const { dragging, offsetLeft } = this;
      if (dragging) {
        const currentX = this.handleTouchEvent(event).clientX;
        const position = ((currentX - offsetLeft) / this.sliderTrack.offsetWidth) * 100;
        const nextValue = (position * (this.max - this.min)) / 100 + this.min;
        // https://stackoverflow.com/q/14627566
        const roundedNextValue = Math.ceil(nextValue / this.step) * this.step;
        this.setValue(roundedNextValue);
      }
    };
    this.onDragEnd = () => {
      this.dragging = false;
      emitEvent(this, 'scaleChange', this.value);
      this.removeGlobalListeners();
    };
    this.setValue = (nextValue) => {
      this.value = this.clamp(nextValue);
      emitEvent(this, 'scaleInput', this.value);
    };
    this.setPosition = () => {
      if (!this.value) {
        this.position = 0;
        return;
      }
      const clampedValue = this.clamp(this.value);
      // https://stackoverflow.com/a/25835683
      this.position = ((clampedValue - this.min) * 100) / (this.max - this.min);
    };
    this.clamp = (val) => {
      return Math.min(Math.max(val, this.min), this.max);
    };
    this.onDragging = this.onDragging.bind(this);
    this.onDragEnd = this.onDragEnd.bind(this);
  }
  componentWillLoad() {
    if (this.sliderId == null) {
      this.sliderId = 'slider-' + i++;
    }
    this.setPosition();
  }
  disconnectedCallback() {
    this.removeGlobalListeners();
  }
  componentDidLoad() {
    if (this.customColor !== undefined) {
      statusNote({
        tag: 'deprecated',
        message: `Property "customColor" is deprecated. 
          Please use css variable "--background-bar" to set the slider-bar color;
          e.g. <scale-slider value="20" style="--background-bar: green"></scale-slider>`,
        type: 'warn',
        source: this.hostElement,
      });
    }
  }
  handleTouchEvent(event) {
    return event.type.indexOf('touch') === 0 ? event.touches[0] : event;
  }
  handleValueChange() {
    this.setPosition();
  }
  addGlobalListeners() {
    window.addEventListener('mousemove', this.onDragging.bind(this));
    window.addEventListener('mouseup', this.onDragEnd.bind(this));
    window.addEventListener('touchmove', this.onDragging.bind(this));
    window.addEventListener('touchend', this.onDragEnd.bind(this));
  }
  removeGlobalListeners() {
    window.removeEventListener('mousemove', this.onDragging);
    window.removeEventListener('mouseup', this.onDragEnd);
    window.removeEventListener('touchmove', this.onDragging);
    window.removeEventListener('touchend', this.onDragEnd);
  }
  render() {
    return (h(Host, null,
      this.styles && h("style", null, this.styles),
      h("div", { part: this.getBasePartMap(), class: this.getCssClassMap() },
        !!this.label && (h("label", { part: "label", class: "slider__label", id: `${this.sliderId}-label`, htmlFor: this.sliderId }, this.label)),
        h("div", { part: "track-wrapper", class: "slider__track-wrapper" },
          h("div", { part: "track", class: "slider__track", ref: (el) => (this.sliderTrack = el) },
            h("div", { part: "bar", class: "slider__bar", style: {
                width: `${this.position}%`,
                backgroundColor: this.customColor
                  ? this.customColor
                  : this.disabled
                    ? `var(--background-bar-disabled)`
                    : `var(--background-bar)`,
              } }),
            h("div", { part: "thumb-wrapper", class: "slider__thumb-wrapper", style: { left: `${this.position}%` }, onMouseDown: this.onButtonDown, onTouchStart: this.onButtonDown },
              h("div", { part: "thumb", class: "slider__thumb", tabindex: "0", role: "slider", id: this.sliderId, "aria-valuemin": this.min, "aria-valuenow": this.value, "aria-valuemax": this.max, "aria-valuetext": `${this.value}`, "aria-labelledby": `${this.sliderId}-label`, "aria-orientation": "horizontal", "aria-disabled": this.disabled, onKeyDown: this.onKeyDown }))),
          h("input", { type: "hidden", value: this.value, name: this.name }),
          this.showValue && (h("div", { part: "display-value", class: "slider__display-value" },
            this.value != null && this.value.toFixed(this.decimals),
            this.value != null && this.unit))))));
  }
  getBasePartMap() {
    return this.getCssOrBasePartMap('basePart');
  }
  getCssClassMap() {
    return this.getCssOrBasePartMap('css');
  }
  getCssOrBasePartMap(mode) {
    const component = 'slider';
    const prefix = mode === 'basePart' ? '' : `${component}--`;
    return classNames(component, this.disabled && `${prefix}disabled`, this.trackSmall && `${prefix}track-small`, this.thumbLarge && `${prefix}thumb-large`);
  }
  static get is() { return "scale-slider"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["./slider.css"]
  }; }
  static get styleUrls() { return {
    "$": ["slider.css"]
  }; }
  static get properties() { return {
    "name": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) the name of the slider"
      },
      "attribute": "name",
      "reflect": false
    },
    "value": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) the display value of the slider"
      },
      "attribute": "value",
      "reflect": false
    },
    "min": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "t(optional) he minimal value of the slider"
      },
      "attribute": "min",
      "reflect": false,
      "defaultValue": "0"
    },
    "max": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) the maximal value of the slider"
      },
      "attribute": "max",
      "reflect": false,
      "defaultValue": "100"
    },
    "step": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) the step size to increase or decrease when dragging slider"
      },
      "attribute": "step",
      "reflect": false,
      "defaultValue": "1"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) slider label"
      },
      "attribute": "label",
      "reflect": false
    },
    "showValue": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) slider display value"
      },
      "attribute": "show-value",
      "reflect": false,
      "defaultValue": "true"
    },
    "unit": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) slider value unit"
      },
      "attribute": "unit",
      "reflect": false,
      "defaultValue": "'%'"
    },
    "decimals": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "0 | 1 | 2",
        "resolved": "0 | 1 | 2",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) number of decimal places"
      },
      "attribute": "decimals",
      "reflect": false,
      "defaultValue": "0"
    },
    "customColor": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "name": "deprecated",
            "text": "- optional) slider custom color"
          }],
        "text": ""
      },
      "attribute": "custom-color",
      "reflect": false
    },
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) disabled"
      },
      "attribute": "disabled",
      "reflect": false,
      "defaultValue": "false"
    },
    "trackSmall": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) smaller track"
      },
      "attribute": "track-small",
      "reflect": false,
      "defaultValue": "false"
    },
    "thumbLarge": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) larger thumb"
      },
      "attribute": "thumb-large",
      "reflect": false,
      "defaultValue": "false"
    },
    "sliderId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) Slider id"
      },
      "attribute": "slider-id",
      "reflect": false
    },
    "styles": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "(optional) Injected CSS styles"
      },
      "attribute": "styles",
      "reflect": false
    }
  }; }
  static get states() { return {
    "position": {}
  }; }
  static get events() { return [{
      "method": "scaleChange",
      "name": "scale-change",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      }
    }, {
      "method": "scaleChangeLegacy",
      "name": "scaleChange",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [{
            "name": "deprecated",
            "text": "in v3 in favor of kebab-case event names"
          }],
        "text": ""
      },
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      }
    }, {
      "method": "scaleInput",
      "name": "scale-input",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      }
    }, {
      "method": "scaleInputLegacy",
      "name": "scaleInput",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [{
            "name": "deprecated",
            "text": "in v3 in favor of kebab-case event names"
          }],
        "text": ""
      },
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      }
    }]; }
  static get elementRef() { return "hostElement"; }
  static get watchers() { return [{
      "propName": "value",
      "methodName": "handleValueChange"
    }]; }
}
