import { LitElement, html, css } from 'lit-element'
import { property } from '../../commons/decorators'

import '@material/mwc-fab/mwc-fab'
import '@polymer/paper-dialog/paper-dialog'
import { saveAs } from 'file-saver'

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

import { togglefullscreen } from '@things-shell/client-utils'
// import '../../commons/board-preview'
import '../../components/things-scene-viewer/things-scene-viewer'

import './edit-toolbar/edit-toolbar'
import './component-toolbar/component-toolbar'
import './property-sidebar/property-sidebar'

import { i18next } from '../../components/i18next'
import elements from '../../things-scene-components-with-tools.import'

class BoardModeler extends connect(store)(LitElement) {
  constructor() {
    super()

    // https://webpack.js.org/guides/code-splitting/#dynamic-imports
    // 동적 임포트로 bundle splitting을 시도했으나, es2015 모듈에서는 안되는 듯.
    // import(
    //   /* webpackChunkName: "components-with-tools" */
    //   /* webpackMode: "lazy" */
    //   '../../things-scene-components-with-tools.import').then(elements => {
    //     store.dispatch({
    //       type: 'MODULE-PLUGIN',
    //       elements
    //     });
    //   }).catch(error => 'An error occurred while loading the component');

    /* 각 모듈의 locale정보로 resource bundle을 추가한다. */
    for (let element in elements) {
      let locales = elements[element].locales

      locales &&
        Object.keys(locales).forEach(lng => {
          i18next.addResourceBundle(lng, 'translations', locales[lng], true, true)
        })
    }

    store.dispatch({
      type: 'MODULE-PLUGIN',
      elements
    })
  }

  static get is() {
    return 'board-modeler'
  }

  // statePath: 'boardCurrent.name'
  @property({ type: String })
  boardName = ''

  // statePath: 'boardCurrent.model'
  @property({ type: Object })
  model = null

  // statePath: 'route.rootPath'
  @property({ type: String })
  baseUrl = ''

  @property({ type: Array })
  selected = []

  @property({ type: Number })
  mode = 1

  /* Transform Mode - 'translate' | 'scale' | 'rotate' */
  @property({ type: String })
  transformMode = 'translate'

  /* Space Mode - 'world' | 'local' */
  @property({ type: String })
  spaceMode = 'world'

  @property({ type: Object })
  provider = null

  @property({ type: Boolean })
  hideProperty = false

  @property({ type: String })
  overlay = null

  @property({ type: Object })
  scene = null

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

          overflow: hidden;
        }

        div {
          flex: 1;

          display: flex;
          flex-direction: row;
        }

        things-scene-viewer {
          flex: 1;
        }

        #scene-wrap {
          position: relative;
        }

        mwc-fab {
          position: absolute;
          right: 15px;
          bottom: 15px;
        }

        #transform-mode {
          position: absolute;
          right: 0px;
          top: 0px;
          align-items: center;
          background-color: darkgray;
          margin: 4px;
          padding: 0 12px 0 0;
        }

        #transform-mode > span {
          width: 24px;
          text-align: center;
        }

        #transform-mode > span[active] {
          background-color: red;
        }
      `
    ]
  }

  stateChanged(state) {
    if (state.route.page !== 'modeler') {
      this.boardName = null
      this.model = null
      this.baseUrl = null
      this.board = state.boardCurrent

      return
    }

    if (this.board !== state.boardCurrent) {
      this.board = state.boardCurrent
      this.boardName = this.board.name
      this.model = {
        ...this.board.model
      }
      this.baseUrl = state.route.rootPath
    }
  }

  firstUpdated() {
    this.addEventListener('sidebar-collapsed-changed', () => {
      this.shadowRoot.getElementById('scene').resize()
    })
  }

  updated(change) {}

  render() {
    return html`
      <edit-toolbar
        id="edittoolbar"
        .scene=${this.scene}
        .selected=${this.selected}
        ?hide-property=${this.hideProperty}
        @hide-property-changed=${e => (this.hideProperty = e.detail.value)}
        @open-preview=${e => this.onOpenPreview(e)}
        @download-model=${e => this.onDownloadModel(e)}
        @modeler-fullscreen=${e => this.onFullscreen(e)}>
      </edit-toolbar>
      
      <div>
      
        <component-toolbar
          .scene=${this.scene}
          .mode=${this.mode}
          @mode-changed=${e => {
            this.mode = e.detail.value
          }}>
        </component-toolbar>
      
        <div id="scene-wrap">
          <things-scene-viewer 
            id="scene" 
            .scene=${this.scene} 
            @scene-changed=${e => {
              this.scene = e.detail.value
            }}
            .model=${this.$model}
            .selected=${this.selected} 
            @selected-changed=${e => {
              this.selected = e.detail.value
            }}
            .mode=${this.mode} 
            @mode-changed=${e => {
              this.mode = e.detail.value
            }}
            @contextmenu=${e => this.onContextMenu(e)}
            .transformMode=${this.transformMode}
            .spaceMode=${this.spaceMode}
            fit="ratio"
            .baseUrl=${this.baseUrl}
            .provider=${this.provider}
            .name="modeler">
            <things-scene-layer type="selection-layer"></things-scene-layer>
            <things-scene-layer type="modeling-layer"></things-scene-layer>
            <things-scene-layer type="guide-layer">
              <things-scene-property name="ruler" value="disabled"></things-scene-property>
            </things-scene-layer>
            <things-scene-layer type="shift-layer">
              <things-scene-property 
                name="text" 
                .value=${this.overlay}>
              </things-scene-property>
              <things-scene-property name="alpha" value=0.3></things-scene-property>
              <things-scene-property name="fontFamily" value="arial"></things-scene-property>
              <things-scene-property name="fontSize" value=30 type="number"></things-scene-property>
              <things-scene-property name="fontColor" value="navy"></things-scene-property>
              <things-scene-property name="textBaseline" value="top"></things-scene-property>
              <things-scene-property name="textAlign" value="left"></things-scene-property>
              <things-scene-property name="paddingTop" value=50 type="number"></things-scene-property>
              <things-scene-property name="paddingLeft" value=50 type="number"></things-scene-property>
            </things-scene-layer>
            <things-scene-layer type="tag-layer"></things-scene-layer>
            <things-scene-handler type="text-editor"></things-scene-handler>
            <things-scene-handler type="move-handler"></things-scene-handler>
          </things-scene-viewer>
      
          <mwc-fab 
            icon="save"
            @tap=${e => this.onTapSave(e)} 
            title="save">
          </mwc-fab>

          <div id="transform-mode">
            <span
              ?active=${this.transformMode == 'translate'}
              @click=${e => (this.transformMode = 'translate')}
            >T</span>
            <span
              ?active=${this.transformMode == 'rotate'}
              @click=${e => (this.transformMode = 'rotate')}
            >R</span>
            <span
              ?active=${this.transformMode == 'scale'}
              @click=${e => (this.transformMode = 'scale')}
            >S</span>
            <input
              type="checkbox"
              @change=${e => (this.spaceMode = e.target.checked ? 'local' : 'world')}
              ?checked=${this.spaceMode == 'local'}>
            <label>local</lobel>
          </div>
        </div>
      
        <property-sidebar
          .scene=${this.scene} 
          .selected=${this.selected} 
          ?collapsed=${this.hideProperty}>
        </property-sidebar>
      </div>
    `
  }

  onOpenPreview() {
    this.previewModel = JSON.parse(JSON.stringify(this.scene.model))

    /*
     * paper-dialog appears behind backdrop when inside a <app-header-layout ..
     * https://github.com/PolymerElements/paper-dialog/issues/152
     **/

    var preview = document.createElement('board-viewer')

    preview.style.width = '100%'
    preview.style.height = '100%'
    preview.style.margin = '0'
    preview.style.padding = '0'
    preview.style.flex = 1
    preview.board = {
      id: 'preview',
      model: this.previewModel
    }
    preview.provider = this.provider

    var dialog = document.createElement('paper-dialog')

    dialog.style.width = '100%'
    dialog.style.height = '100%'
    dialog.style.display = 'flex'
    dialog.style['flex-direction'] = 'column'
    dialog.setAttribute('with-backdrop', true)
    dialog.setAttribute('auto-fit-on-attach', true)
    dialog.setAttribute('always-on-top', true)
    dialog.addEventListener('iron-overlay-closed', () => {
      preview.board = null
      dialog.parentNode.removeChild(dialog)
    })

    dialog.appendChild(preview)
    document.body.appendChild(dialog)

    dialog.open()

    requestAnimationFrame(() => {
      dialog.open()
      dispatchEvent(new Event('resize'))
    })
  }

  onDownloadModel() {
    if (!this.scene) return

    var model = JSON.stringify(this.model, null, 2)
    var filename = (this.boardName || 'NONAME') + '-' + Date.now() + '.json'
    saveAs(new Blob([model], { type: 'application/octet-stream' }), filename)
  }

  onTapSave() {
    this.shadowRoot.getElementById('edittoolbar').saveBoard()
  }

  onFullscreen() {
    togglefullscreen(this)
  }
}

customElements.define(BoardModeler.is, BoardModeler)
