type UniSwitchChangeEventDetail = {
  value : boolean
}

export class UniSwitchChangeEvent extends UniCustomEvent<UniSwitchChangeEventDetail> {
  constructor(value : boolean) {
    super('change', { value } as UniSwitchChangeEventDetail)
  }
}

export class UniSwitchElement extends UniFormControlElement<boolean> implements UniCustomElement {
  static get observedAttributes() : Array<string> {
    return [
      'checked',
      'disabled',
      'value',
      'background-color',
      'active-background-color',
      'fore-color',
      'active-fore-color',
      'color'
    ];
  }

  private switchThumb! : UniElement
  private _initialChecked = false
  private _initialCheckedFlag = false
  private _checked = false

  constructor() {
    super()

    const switchTrackStyle = this.style
    switchTrackStyle.setProperty('borderStyle', 'solid')
    switchTrackStyle.setProperty('borderWidth', '2px')
    switchTrackStyle.setProperty('borderRadius', '16px')
    switchTrackStyle.setProperty('width', '52px')
    switchTrackStyle.setProperty('height', '32px')
    switchTrackStyle.setProperty('transitionDuration', '0.1s')
    switchTrackStyle.setProperty('transitionProperty', 'backgroundColor')

    const switchThumb = this.uniPage.createElement('view')
    const switchThumbStyle = switchThumb.style
    switchThumbStyle.setProperty('width', '28px')
    switchThumbStyle.setProperty('height', '28px')
    switchThumbStyle.setProperty('borderRadius', '14px')

    this.switchThumb = switchThumb

    this.addEventListener('click', (e: UniPointerEvent) => {
      "[weak self]"
      e.stopPropagation()
      if (this.disabled) {
        return
      }
      this.checked = !this.checked
      this.dispatchEvent(new UniSwitchChangeEvent(this.checked))
    })
  }

  // form
  override get name() : string {
    return this.getAttributeValue('name', '')
  }
  override set name(value : string) {
    this.setAttribute('name', value)
  }

  override get value() : boolean {
    return this._checked
  }
  override set value(value: boolean) {
    this._checked = value
  }

  override reset() {
    this.checked = this._initialChecked
  }

  connectedCallback() {
    // TODO 需要先设置 transform 否者会有动画效果
    this.updateCheckStatus()
    this.updateCheckStatusColor()
    this.switchThumb.style.setProperty('transitionDuration', '0.3s')
    this.switchThumb.style.setProperty('transitionProperty', 'transform')
    this.appendChild(this.switchThumb)
  }

  disconnectedCallback() {
    this.removeChild(this.switchThumb)
  }

  attributeChangedCallback(name : string, oldValue : any | null, newValue : any | null) {
    switch (name) {
      case 'checked':
        const value = (typeof newValue == 'string' || newValue == true) ? true : false
        if (!this._initialCheckedFlag) {
          this._initialCheckedFlag = true
          this._initialChecked = value
        }
        this.checked = value
        break;
      case 'disabled':
      case 'background-color':
      case 'active-background-color':
      case 'fore-color':
      case 'active-fore-color':
      case 'color':
        if (this.isConnected) {
          this.updateCheckStatusColor()
        }
        break;
    }
  }

  get disabled() : boolean {
    return this.getAttribute('disabled') == 'true' ? true : false
  }

  get checked() : boolean {
    return this._checked
  }

  set checked(value : boolean) {
    this._checked = value
    if (this.isConnected) {
      this.updateCheckStatus()
      this.updateCheckStatusColor()
    }
  }

  get backgroundColor() : string {
    return this.getAttributeValue('backgroundColor', '#e9e9ea')
  }

  get activeBackgroundColor() : string {
    return this.getAttributeValue('activeBackgroundColor', this.color)
  }

  get foreColor() : string {
    return this.getAttributeValue('foreColor', '#fff')
  }

  get activeForeColor() : string {
    return this.getAttributeValue('activeForeColor', '#fff')
  }

  get color() : string {
    return this.getAttributeValue('color', '#007aff')
  }

  updateCheckStatus() {
    if (this.checked) {
      this.switchThumb.style.setProperty('transform', 'translateX(20px)')
    } else {
      this.switchThumb.style.setProperty('transform', 'translateX(0px)')
    }
  }

  updateCheckStatusColor() {
    if (this.disabled) {
      this.style.setProperty('opacity', '0.7')
    } else {
      this.style.setProperty('opacity', '1')
    }

    if (this.checked) {
      // track
      this.style.setProperty('backgroundColor', this.activeBackgroundColor)
      this.style.setProperty('borderColor', this.activeBackgroundColor)

      // thumb
      this.switchThumb.style.setProperty('backgroundColor', this.activeForeColor)
    } else {
      // track
      this.style.setProperty('backgroundColor', this.backgroundColor)
      this.style.setProperty('borderColor', this.backgroundColor)

      // thumb
      this.switchThumb.style.setProperty('backgroundColor', this.foreColor)
    }
  }

  private getAttributeValue(key : string, defaultValue : string) : string {
    const value = this.getAttribute(key)
    if (value != null && value!.length > 0) {
      return value!
    }
    return defaultValue
  }
}