<template>
  <main>
    <deck-card-editor-menu
      :active="contentInFocus"
      @action="editorAction"
      v-model="menuState"
    />

    <div
      :ref="content"
      class="card-content"
      :contenteditable="active"
      @focus="start"
      @click="syncMenuStateIfFocussed"
      @keyup="syncMenuStateOnKeyPress"
      @blur="stop"
    >
      <h2>card content</h2>
      <hr />
      <p><b>foo:</b> boom</p>
      <p><b>bar:</b> blam</p>
      <hr />
      <p>Some description maybe?</p>
    </div>
  </main>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import DeckCardEditorMenu from '@/components/deck-card-editor-menu.vue'
import {
  elementNameToMenuState,
  getElementAndParentName,
  marks,
  blocks,
  State,
  movementKeys,
  controlSequenceKeys
} from '@/editor.ts'

@Component({
  components: { DeckCardEditorMenu }
})
export default class DeckCardEditor extends Vue {
  @Prop() public readonly active!: boolean
  @Prop() public readonly content!: Card['content']

  private contentInFocus = false

  private menuState: State = {
    bold: false,
    italic: false,
    paragraph: true,
    heading1: false,
    heading2: false,
    heading3: false,
    bulletList: false,
    spacer: false,
    separator: false,
    statBlock: false
  }

  private clearMarks () {
    marks.forEach(mark => {
      this.menuState[mark] = false
    })
  }

  private toggleBlock (name: string) {
    blocks.forEach(block => {
      this.menuState[block] = false
    })
    this.menuState[name] = true
  }

  private setMenuState (elementName: string, parentName?: string) {
    const stateName = elementNameToMenuState[elementName]

    // marks are always inside a block element
    if (marks.indexOf(stateName) >= 0 && parentName) {
      const parentStateName = elementNameToMenuState[parentName]
      // marks are inclusive like checkboxes
      this.menuState[stateName] = true
      // but blocks are exclusive like radio buttons
      this.toggleBlock(parentStateName)
    } else {
      this.clearMarks()
      this.toggleBlock(stateName)
    }
  }

  private editorAction (action: string) {
    console.log('action', action)
    // const content = this.$refs.content
  }

  private syncMenuState () {
    const sel = window.getSelection()?.focusNode
    if (!sel) return

    const [elementName, parentName] = getElementAndParentName(sel)
    console.log('focussed element', elementName, parentName)
    if (!elementName) return

    this.setMenuState(elementName, parentName)
  }

  private syncMenuStateIfFocussed () {
    if (this.contentInFocus) this.syncMenuState()
  }

  private syncMenuStateOnKeyPress (event: KeyboardEvent) {
    // undo/redo/cut/paste
    const isCtrlSq = event.ctrlKey && controlSequenceKeys.indexOf(event.key) >= 0
    // arrow keys, enter, delete, etc
    const isMove = movementKeys.indexOf(event.key) >= 0

    if (isCtrlSq || isMove) this.syncMenuState()
  }

  private start () {
    this.contentInFocus = true
    this.syncMenuState()
  }

  private stop () {
    this.contentInFocus = false
  }
}
</script>

<style scoped>
.card-content p {
  margin: 0;
  line-height: 1.2;
}

.card-content ul {
  list-style-position: inside;
  margin: 0;
  padding-left: .5em;
}
.card-content li > p {
  display: inline;
}

.card-content h2 {
  font-size: 1.4rem;
  color: var(--highlight-color);
  margin: 0;
  font-weight: normal;
}

.card-content h3 {
  font-size: 1.4rem;
  color: var(--highlight-color);
  margin: 0 0 .2em 0;
  font-weight: normal;
  font-variant: small-caps;
  line-height: .9em;
  border-bottom: 1px solid var(--highlight-color);
}

.card-content hr {
  height: 0;
  margin: .2em 0;
  border: 2px solid var(--highlight-color);
}
.card-content hr.pointing-right {
  height: 0;
  margin: .2em 0;
  border-style: solid;
  border-width: 2px 0 2px 220px;
  border-color: transparent transparent transparent var(--highlight-color);
}
.card-content hr.pointing-left {
  height: 0;
  margin: .2em 0;
  border-style: solid;
  border-width: 2px 220px 2px 0;
  border-color: transparent var(--highlight-color) transparent transparent;
}
[contenteditable="true"] { outline: none; }
</style>
