import '@material/mwc-icon'
import '@material/mwc-button'
import '@operato/property-editor/ox-properties-dynamic-view.js'
import '@operato/markdown'
import '@operato/board/ox-board-viewer.js'

import { css, html, LitElement } from 'lit'
import { customElement, property } from 'lit/decorators.js'

import { ScrollbarStyles } from '@operato/styles'
import { i18next } from '@operato/i18n'

import { convertPropertyValue } from './utils'

@customElement('stream-info')
export class StreamInfo extends LitElement {
  static styles = [
    ScrollbarStyles,
    css`
      :host {
        background-color: white;
        font-size: 12px;
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        border: 2px solid var(--primary-color);
        border-radius: 3px;

        --mdc-icon-size: 12px;
      }

      [header] {
        background-color: var(--primary-color);
        user-select: none;
        align-items: center;
        color: #eee;
        padding: 0 2px;

        display: flex;
      }

      [header] mwc-icon {
        margin-left: auto;
        align-self: center;
      }

      [content] {
        overflow: auto;
      }

      table {
        border-collapse: collapse;
        background-color: #fff;
        width: 100%;
        margin: auto;
      }
      tr {
        border-bottom: var(--border-dark-color);
      }
      th {
        border-top: 2px solid var(--focus-background-color);
        border-right: 1px solid var(--primary-color);
        background-color: var(--secondary-text-color);
        padding: var(--padding-narrow);
        color: var(--theme-white-color);
      }

      tr td:first-child {
        background-color: rgba(0, 0, 0, 0.05);
        text-align: right;
      }
      td {
        padding: var(--padding-narrow);
        border-right: var(--border-dark-color);
        text-align: right;
        font-size: 0.8em;
      }
      td:last-child {
        border-right: 0;
      }

      tr[doubleline] {
        border-bottom: 2px double rgba(0, 0, 0, 0.2);
      }

      [subTh] {
        text-align: center !important;
        font-weight: bold;
      }

      [subTh2] {
        background-color: rgba(var(--primary-color-rgb), 0.5) !important;
        color: #fff;
        text-align: center !important;
        font-weight: bold;
        font-size: 1em;
      }
      [formation] td:first-child {
        background-color: rgba(var(--primary-color-rgb), 0.05) !important;
        font-weight: bold;
        color: var(--primary-color);
      }
      [formation]:nth-child(odd) {
        background-color: rgba(var(--primary-color-rgb), 0.02);
      }

      tr:hover,
      [formation]:hover {
        background-color: var(--focus-background-color) !important;
      }
    `
  ]

  @property({ type: Object }) stream?: any //StreamLine

  private dragEndHandler = this.onDragEnd.bind(this) as EventListener
  private dragMoveHandler = this.onDragMove.bind(this) as EventListener

  connectedCallback(): void {
    super.connectedCallback()

    document.addEventListener('mouseup', this.dragEndHandler)
    document.addEventListener('mousemove', this.dragMoveHandler)
  }

  disconnectedCallback(): void {
    super.disconnectedCallback()

    document.removeEventListener('mouseup', this.dragEndHandler)
    document.removeEventListener('mousemove', this.dragMoveHandler)
  }

  render() {
    const { refid, streamType: type } = this.stream?.state || {}
    const { data, from, to } = this.stream

    return html`
      <div header @mousedown=${this.onDragStart.bind(this)} draggable="false">
        Stream Information<mwc-icon @click=${e => this.dispatchEvent(new CustomEvent('close'))}>close</mwc-icon>
      </div>
      <div content>
        <table>
          <tr>
            <td subTh colspan="2">이름</td>
            <td>${refid}</td>
          </tr>
          <tr>
            <td subTh colspan="2">타입</td>
            <td>${type}</td>
          </tr>
          <tr>
            <td subTh colspan="2">노드 이름 (Out → In)</td>
            <td>${`${from.anchor} → ${to.anchor}`}</td>
          </tr>

          ${data
            ? this.dataContent(data)
            : html`<tr>
                <td colspan="3">
                  Not calculated yet.<br />
                  Please, analyze process first.
                </td>
              </tr>`}
        </table>
      </div>
    `
  }

  dataContent({ Y = {}, m = NaN, T = NaN, p = NaN, h = NaN, MC = NaN, spheat = NaN, htr = NaN, pwr = NaN }) {
    const fractions = Object.entries(Y).map(([material, fraction]) => {
      return { material, fraction }
    })

    return html`
      <tr>
        <td subTh colspan="2">${i18next.t('label.mass')} (kg)</td>
        <td>${convertPropertyValue(m)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">${i18next.t('label.temperature')} (K)</td>
        <td>${convertPropertyValue(T)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">${i18next.t('label.pressure')} (Pa)</td>
        <td>${convertPropertyValue(p)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">비엔탈피 (J/kg)</td>
        <td>${convertPropertyValue(h)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">${i18next.t('label.moisture-content')} (%)</td>
        <td>${convertPropertyValue(MC)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">비열 (J/(kg·K))</td>
        <td>${convertPropertyValue(spheat, 4)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">${i18next.t('label.electric-power')} (W)</td>
        <td>${convertPropertyValue(pwr)}</td>
      </tr>
      <tr>
        <td subTh colspan="2">${i18next.t('label.out-heat')} (W)</td>
        <td>${convertPropertyValue(htr)}</td>
      </tr>

      ${fractions.map(
        ({ material, fraction }, idx) => html`
          <tr formation>
            ${idx == 0
              ? html` <td subTh2 rowspan=${fractions.length}>${i18next.t('label.mass-fraction')}</td> `
              : html``}
            <td>${material}</td>
            <td>${Number(fraction).toFixed(3)}</td>
          </tr>
        `
      )}
    `
  }

  private dragStart?: { x: number; y: number }

  onDragStart(e: MouseEvent) {
    e.stopPropagation()

    if (e.button == 0) {
      this.dragStart = {
        x: e.clientX,
        y: e.clientY
      }
    }

    return false
  }

  onDragMove(e: Event) {
    if (!this.dragStart) {
      return false
    }

    e.stopPropagation()
    e.preventDefault()

    var x = (e as MouseEvent).clientX,
      y = (e as MouseEvent).clientY

    const dragStart = { x, y }

    x -= this.dragStart.x
    y -= this.dragStart.y

    this.dragStart = dragStart

    this.style.left =
      Math.min(this.parentElement!.offsetWidth - this.offsetWidth, Math.max(0, this.offsetLeft + x)) + 'px'
    this.style.top =
      Math.min(this.parentElement!.offsetHeight - this.offsetHeight, Math.max(0, this.offsetTop + y)) + 'px'

    return false
  }

  onDragEnd(e: Event) {
    if (this.dragStart) {
      e.stopPropagation()
      e.preventDefault()

      delete this.dragStart
    }
  }
}
