import { LitElement, html, css } from 'lit-element'

import '@material/mwc-fab/mwc-fab'
import '@material/mwc-icon/mwc-icon'

import '@polymer/app-layout/app-toolbar/app-toolbar'

import 'web-animations-js'

import { connect } from 'pwa-helpers/connect-mixin.js'
import { store } from '../../reducer/store'

import '../../components/things-scene-viewer/things-scene-viewer'
import '../../layouts/page-toolbar/page-toolbar'

import '../../components/things-scene-viewer/things-scene-player'
import '../../components/things-player/things-player-carousel'
import '../../components/things-player/things-player-cube'
import '../../components/things-player/things-player-flipcard'
import '../../components/things-player/things-player-flipcard-edge'
import '../../components/things-player/things-player-grid'
import '../../components/things-player/things-player-enlarge-grid'
import { fullscreen } from '../../commons/utils'

import './board-player-dialog'

class BoardPlayer extends connect(store)(LitElement) {
  static get is() {
    return 'board-player'
  }

  static get properties() {
    return {
      // statePath: 'route.page'
      page: String, // '_onPageChanged'
      // statePath: 'boardList'
      boards: Array, // '_onBoardsChanged'
      // statePath: 'drawer.collapsed'
      drawerCollapsed: Boolean,

      transition: String,
      playtime: Number,
      columns: Number,
      rows: Number,
      provider: Object,
      started: Boolean
    }
  }

  static get styles() {
    return [
      css`
        :host {
          display: flex;
          flex-direction: column;
          width: 100%;
          height: 100%;

          overflow: hidden;
        }

        #player-area {
          flex: 1;

          display: flex;
          flex-direction: column;
          overflow: hidden;
        }

        #player-area > * {
          flex: 1;
        }

        things-scene-player {
          width: 100%;
          height: 100%;
        }

        things-scene-player[front] {
          background: black;
        }

        things-scene-player[back] {
          background: black;
        }

        #fab {
          position: absolute;
          right: 15px;
          bottom: 15px;
        }

        #fab[hidden] {
          display: none;
        }
      `
    ]
  }

  constructor() {
    super()

    this.transition = 'carousel'
    this.playtime = 30
    this.columns = 1
    this.rows = 1
    this.started = false
  }

  stateChanged(state) {
    this.page = state.route.page
    this.boards = state.boardList
    this.drawerCollapsed = state.drawer.collapsed
  }

  updated(change) {
    change.has('page') && this._onPageChanged(this.page, change.page)
  }

  render() {
    return html`
      <page-toolbar> </page-toolbar>

      <div
        id="player-area"
        @keydown=${e => this._onKeydown(e)}
        @tap=${e => this._onTap(e)}
        @mousemove=${e => this._onMousemove(e)}
        @transform=${e => this._onTransform(e)}
        tabindex="-1"
      >
        ${
          this.page == 'player' && this.started
            ? html`
                ${
                  this.transition == 'flip-card'
                    ? html`
                        <things-player-flipcard axis="y" .rows=${this.rows} .columns=${this.columns} player>
                          ${
                            this.boards.map(
                              item => html`
                                <things-scene-player page .sceneId=${item.id} fit="both" .provider=${this.provider}>
                                </things-scene-player>
                              `
                            )
                          }
                        </things-player-flipcard>
                      `
                    : html``
                }
                ${
                  this.transition == 'flip-card2'
                    ? html`
                        <things-player-flipcard-edge axis="y" .rows=${this.rows} .columns=${this.columns} player>
                          ${
                            this.boards.map(
                              item => html`
                                <things-scene-player page .sceneId=${item.id} fit="both" .provider=${this.provider}>
                                </things-scene-player>
                              `
                            )
                          }
                        </things-player-flipcard-edge>
                      `
                    : html``
                }
                ${
                  this.transition == 'carousel'
                    ? html`
                        <things-player-carousel
                          axis="y"
                          .rows=${this.rows}
                          .columns=${this.columns}
                          backface-visibility="false"
                          player
                        >
                          ${
                            this.boards.map(
                              item => html`
                                <things-scene-player page .sceneId=${item.id} fit="both" .provider=${this.provider}>
                                </things-scene-player>
                              `
                            )
                          }
                        </things-player-carousel>
                      `
                    : html``
                }
                ${
                  this.transition == 'enlarge-grid'
                    ? html`
                        <things-player-enlarge-grid
                          axis="y"
                          .rows=${this.rows}
                          .columns=${this.columns}
                          backface-visibility="false"
                          player
                        >
                          ${
                            this.boards.map(
                              item => html`
                                <things-scene-player page .sceneId=${item.id} fit="both" .provider=${this.provider}>
                                </things-scene-player>
                              `
                            )
                          }
                        </things-player-enlarge-grid>
                      `
                    : html``
                }
              `
            : html``
        }
      </div>

      <mwc-fab
        id="fab"
        @mouseover=${e => this._onMouseoverFab(e)}
        @tap=${e => this._onTapFullscreen(e)}
        icon="fullscreen"
        title="fullscreen"
      >
      </mwc-fab>

      <board-player-dialog
        id="setting-dialog"
        .transition=${this.transition}
        @transition-changed=${e => (this.transition = e.detail.value)}
        .playtime=${this.playtime}
        @playtime-changed=${e => (this.playtime = e.detail.value)}
        .rows=${this.rows}
        @rows-changed=${e => (this.rows = e.detail.value)}
        .columns=${this.columns}
        @columns-changed=${e => (this.columns = e.detail.value)}
        @iron-overlay-closed=${e => this._onSettingDialogClosed(e)}
        no-overlap
      >
      </board-player-dialog>
    `
  }

  get fab() {
    return this.shadowRoot.getElementById('fab')
  }

  get playerArea() {
    return this.shadowRoot.getElementById('player-area')
  }

  get settingDialog() {
    return this.shadowRoot.getElementById('setting-dialog')
  }

  _resetFadeTimer(stop) {
    this.fab.hidden = false

    this._fab_animation && this._fab_animation.cancel()

    this._fab_animation = this.fab.animate(
      [
        {
          opacity: 1,
          easing: 'ease-in'
        },
        { opacity: 0 }
      ],
      { duration: 5000 }
    )

    this._fab_animation.finished.then(
      () => {
        this.fab.hidden = true
      },
      () => {}
    )

    stop && this._fab_animation.cancel()
  }

  _onPageChanged(after, before) {
    if (before == 'player' && after !== 'player') {
      this.settingDialog.close()
      this.started && this._stopPlay()
    } else if (after == 'player') {
      this.settingDialog.closingReason = {}
      this.settingDialog.open()
      this.fab.hidden = true
    }
  }

  _onSettingDialogClosed(e) {
    var dialog = e.target

    if (!dialog.closingReason.confirmed) return

    this._startPlay()
    this.playerArea.focus()

    this.fab.hidden = false
  }

  _onMousemove() {
    this._resetFadeTimer()
  }

  _onMouseoverFab() {
    this._resetFadeTimer(true)
  }

  _onTapFullscreen() {
    var collapsed = this.drawerCollapsed

    if (!collapsed) {
      store.dispatch({
        type: 'CLOSE-DRAWER'
      })
    }

    fullscreen(
      this.currentPlayer,
      () => {
        this.fab.hidden = true
        this.playerArea.focus()
      },
      () => {
        this.fab.hidden = false
        this.playerArea.focus()
        if (!collapsed) {
          store.dispatch({
            type: 'OPEN-DRAWER'
          })
        }
      }
    )
  }

  _onTransform() {
    requestAnimationFrame(() => this.started && this._resetTransformTimer())
  }

  _resetTransformTimer() {
    clearTimeout(this._transfer_timer)

    if (this.currentPlayer) {
      this._transfer_timer = setTimeout(() => {
        if (this._transfer_timer) this.currentPlayer.next()
      }, this.playtime * 1000)
    }
  }

  _onTap() {
    this.currentPlayer && this.currentPlayer.next()
  }

  _onKeydown(e) {
    var player = this.currentPlayer

    if (!player) return

    switch (e.keyCode) {
      case 38: // arrow up
        player.axis = 'x'
        player.next()
        break
      case 39: // arrow right
        player.axis = 'y'
        player.next()
        break
      case 40: // arrow down
        player.axis = 'x'
        player.previous()
        break
      case 37: // arrow left
        player.axis = 'y'
        player.previous()
        break
    }
  }

  async _startPlay() {
    if (this.page !== 'player' || !this.boards || this.boards.length == 0) return

    this.started = true

    await this.renderComplete
    this.currentPlayer = this.shadowRoot.querySelector(':not([style*="display: none"])[player]')

    this._resetTransformTimer()
    this._resetFadeTimer()

    this.playerArea.focus()
  }

  async _stopPlay() {
    clearTimeout(this._transfer_timer)

    this.currentPlayer && this.currentPlayer.stop()

    await this.renderComplete
    this.started = false
  }
}

customElements.define(BoardPlayer.is, BoardPlayer)
