import Ticker from '../core/util/Ticker.js'

const PAUSED_BY_ACTION = 1
const PAUSED_BY_INTERSECTION = 2
const PAUSED_BY_DOCUMENT_VISIBILITY = 4
const PAUSED_BY_CONNECTION = 8

/**
 * Element triggering requestAnimationFrame on its update method.
 * @hideconstructor
 */
class DamdomTicker extends HTMLElement {
  constructor() {
    super()

    this._updateBound = this.update.bind(this)

    this._pauseFlag = 0

    const observer = new IntersectionObserver((entries) => {
      let isIntersecting = false
      for (const entry of entries) {
        if (entry.isIntersecting) {
          isIntersecting = true
        }
      }
      if (isIntersecting) {
        this._pauseFlag &= ~PAUSED_BY_INTERSECTION
      } else {
        this._pauseFlag |= PAUSED_BY_INTERSECTION
      }
    })
    observer.observe(this)

    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        this._pauseFlag |= PAUSED_BY_DOCUMENT_VISIBILITY
      } else {
        this._pauseFlag &= ~PAUSED_BY_DOCUMENT_VISIBILITY
      }
    })
  }

  connectedCallback() {
    this._pauseFlag &= ~PAUSED_BY_CONNECTION
    if (document.hidden) {
      this._pauseFlag |= PAUSED_BY_DOCUMENT_VISIBILITY
    }
    if (!(this._pauseFlag & PAUSED_BY_ACTION)) {
      this.update()
    }
  }

  disconnectedCallback() {
    this._pauseFlag |= PAUSED_BY_CONNECTION
  }

  get _pauseFlag() {
    return this.__pauseFlag
  }

  set _pauseFlag(value) {
    if (this.__pauseFlag === value) {
      return
    }
    this.__pauseFlag = value
    if (this.__pauseFlag) {
      Ticker.delete(this._updateBound)
    } else {
      Ticker.add(this._updateBound)
    }
  }

  /**
   * Play element.
   */
  play() {
    this._pauseFlag &= ~PAUSED_BY_ACTION
  }

  /**
   * Pause element.
   */
  pause() {
    this._pauseFlag |= PAUSED_BY_ACTION
  }

  /**
   * Tells whether the element is paused.
   * @type {Boolean}
   * @readonly
   */
  get paused() {
    return !!this._pauseFlag
  }

  /**
   * Update loop method
   */
  update() { }
}

export default DamdomTicker

import Ticker from '../core/util/Ticker.js'

const PAUSED_BY_ACTION = 1
const PAUSED_BY_INTERSECTION = 2
const PAUSED_BY_DOCUMENT_VISIBILITY = 4
const PAUSED_BY_CONNECTION = 8

/**
 * Element triggering and managing a stable requestAnimationFrame loop.
 * @hideconstructor
 */

class DamdomTicker extends HTMLElement {
  #pauseFlagValue
  #callback = () => console.log('DamdomTicker.callback needs to be set')

  constructor() {
    super()

    const observer = new IntersectionObserver((entries) => {
      let isIntersecting = false
      for (const entry of entries) {
        if (entry.isIntersecting) {
          isIntersecting = true
        }
      }
      if (isIntersecting) {
        this.#pauseFlag &= ~PAUSED_BY_INTERSECTION
      } else {
        this.#pauseFlag |= PAUSED_BY_INTERSECTION
      }
    })
    observer.observe(this)

    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
        this.#pauseFlag |= PAUSED_BY_DOCUMENT_VISIBILITY
      } else {
        this.#pauseFlag &= ~PAUSED_BY_DOCUMENT_VISIBILITY
      }
    })
  }

  connectedCallback() {
    this.#pauseFlag &= ~PAUSED_BY_CONNECTION
    if (document.hidden) {
      this.#pauseFlag |= PAUSED_BY_DOCUMENT_VISIBILITY
    }
    if (!(this.#pauseFlag & PAUSED_BY_ACTION)) {
      this.#callback()
    }
  }

  disconnectedCallback() {
    this.#pauseFlag |= PAUSED_BY_CONNECTION
  }

  get #pauseFlag() {
    return this.#pauseFlagValue
  }

  set #pauseFlag(value) {
    if (this.#pauseFlagValue === value) {
      return
    }
    this.#pauseFlagValue = value
    if (this.#pauseFlagValue) {
      Ticker.delete(this.#callback)
    } else {
      Ticker.add(this.#callback)
    }
  }

  /**
   * Play element.
   */
  play() {
    this.#pauseFlag &= ~PAUSED_BY_ACTION
  }

  /**
   * Pause element.
   */
  pause() {
    this.#pauseFlag |= PAUSED_BY_ACTION
  }

  /**
   * Tells whether the element is paused.
   * @type {Boolean}
   * @readonly
   */
  get paused() {
    return !!this.#pauseFlag
  }

  set callback(value) {
    Ticker.delete(this.#callback)
    this.#callback = value
    if (!this.#pauseFlagValue) Ticker.add(this.#callback)
  }
}

export default DamdomTicker

update with private fields