<template>
<div>

  <div v-if="mt != null">
    <h4>Style</h4>
    <table>
      <tr v-for="[subject, style] of subjectStyles()" :key="subject">
        <td>{{subject}}</td>
        <td :style="style">Text</td>
      </tr>
    </table>
  </div>

  <div>
    <button @click="onClickToggleGreek">Toggle greek letter subject</button>
    <button @click="onClickToggleCat">Toggle cat subject</button>
    <button @click="onClickTogglePlanet">Toggle planet subject</button>
    <button @click="onClickActivateAll">Turn on all subjects</button>
    <button @click="onClickDeactivateAll">Turn off all subjects</button>
  </div>
  <div>
    <button @click="onClickToggleGreekLines">Toggle greek letter lines</button>
    <button @click="onClickToggleCatLines">Toggle cat lines</button>
    <button @click="onClickTogglePlanetLines">Toggle planet lines</button>
  </div>
  <div>
    <button @click="onClickTextStyleSubject">Text style subjects</button>
    <button @click="onClickBackgroundStyleSubject">Background style subjects</button>
    <button @click="onClickBorderStyleSubject">Border style subjects</button>
    <button @click="onClickUnderlineStyleSubject">Underline style subjects</button>
  </div>
  <!--<div>
    <button @click="onClickTogglePluto">Add/remove pluto planet</button>
    <button @click="onClickToggleAsteroid">Add/remove asteroid planet</button>
  </div>-->

  <MarkedText id="mt" ref="mt"
    :sourceText="sourceText" :marks="marks" :controller="controller"
    :subjectStyleType="subjectStyleType"
  />

  <div v-if="marksSelected != null">
    <button v-for="(mark, idx) of marksSelected" :key="idx"
      @click="() => onClickSelectMark(mark)"
    >Select mark {{idx}}, {{mark.text}}</button>
  </div>

</div>
</template>



<script lang="ts">
import LeaderLine from 'leader-line'

import MarkedText, * as MT from '@'
import { SubjectStyleType } from '@/Subject'
import { defineComponent, ref } from 'vue'


const SubjectTest = defineComponent({

  name: 'SubjectTest',

  components: {
    MarkedText
  },

  data() {

    const sourceText = [
      [
        'This is to test how subjects work.',
        'The subjects will be (1) greek letters alpha, beta, gamma, delta;',
        '(2) cat types calico, siamese, domestic short hair, domestic long hair;',
        '(3) planets mercury, venus, earth, mars, jupiter.'
      ],
      [
        'Calico kitties are tricolored. They are closest to Earth, and unlike Mars.',
        'That\'s not to say that color is alpha and omega.',
        'Some are allergic, so short hair vs long hair is the psi-n of distinction.',
        'Or maybe just name your siamese "Rho-psi" and leave the rest to the asteroids.'
      ],
      [
        'We should also look at overlaps, though the subjects don\'t lend naturally to this.',
        'But say that catauri was a cat breed.',
        'Tau is a greek letter, so catauri has one subject inside another.',
        'Or say that "hair 3" was a planet; domestic short hair 3 would overlap subjects.'
      ],
      [
        'But pluto is a dog\'s name.'
      ]
    ].map(paragraph => paragraph.join(' ')).join('\n\n')

    const marks = [] as MT.IMark[]

    const subjectStyleType = 'border' as SubjectStyleType

    return {
      sourceText,
      marks,
      subjectStyleType
    }
  },

  methods: {

    initMarks() {

      const greekLetters = {
        subjectMembers: [ 'alpha', 'beta', 'gamma', 'delta', 'omega', 'psi', 'rho', 'tau' ],
        subjectName: 'greek'
      }
      const cats = {
        subjectMembers: [
          'calico', 'siamese', 'domestic short hair', 'domestic long hair',
          'short hair', 'long hair', 'catauri'
        ],
        subjectName: 'cat'
      }
      const planets = {
        subjectMembers: [ 'mercury', 'venus', 'earth', 'mars', 'jupiter', 'asteroids', 'pluto', 'hair 3' ],
        subjectName: 'planet'
      }

      const marks = []
      for (const subjectData of [greekLetters, cats, planets]) {
        for (const subjectMember of subjectData.subjectMembers) {
          const regex = new RegExp(subjectMember, 'gi')
          let match
          // tslint:disable-next-line
          while ((match = regex.exec(this.sourceText)) != null) {
            marks.push({
              begChar: match.index,
              endChar: match.index + match[0].length,
              text: match[0],
              subjects: [subjectData.subjectName]
            } as MT.IMark)
          }
        }
      }

      return marks

    },

    subjectStyles() {
      if (this.mt != null) {
        return ['greek', 'cat', 'planet'].map(
          subject => [subject, (this.mt as MT.IMarkedText).subjectStyle(subject)]
        )
      } else return []
    },


    onClickToggleGreek() {
      if (this.mt) this.mt.toggleSubject('greek')
    },
    onClickToggleCat() {
      if (this.mt) this.mt.toggleSubject('cat')
    },
    onClickTogglePlanet() {
      if (this.mt) this.mt.toggleSubject('planet')
    },

    onClickActivateAll() {
      if (this.mt) this.mt.activateAllSubjects()
    },
    onClickDeactivateAll() {
      if (this.mt) this.mt.deactivateAllSubjects()
    },

    onClickToggleGreekLines() {
      if (this.mt) this.mt.toggleLines('greek')
    },
    onClickToggleCatLines() {
      if (this.mt) this.mt.toggleLines('cat')
    },
    onClickTogglePlanetLines() {
      if (this.mt) this.mt.toggleLines('planet')
    },

    // The 'next tick force update' is just to update the styles in the div, not MarkedText itself
    onClickTextStyleSubject() {
      this.subjectStyleType = 'text'
      this.$nextTick(() => { this.$forceUpdate() })
    },
    onClickBackgroundStyleSubject() {
      this.subjectStyleType = 'background'
      this.$nextTick(() => { this.$forceUpdate() })
    },
    onClickBorderStyleSubject() {
      this.subjectStyleType = 'border'
      this.$nextTick(() => { this.$forceUpdate() })
    },
    onClickUnderlineStyleSubject() {
      this.subjectStyleType = 'underline'
      this.$nextTick(() => { this.$forceUpdate() })
    }

  },

  setup() {

    const marksSelected = ref<MT.IMark[] | null>(null)

    const deselect = () => {
      marksSelected.value = null
    }
    const selectNew = (begChar: number, endChar: number) => {
      marksSelected.value = null
    }
    const selectMarks = (marks: MT.IMark[]) => {
      if (marks.length === 1) {
        marksSelected.value = null
      } else {
        marksSelected.value = marks
      }
    }

    const controller = ref<MT.IController>(new MT.WordSelectionController(
      deselect, selectNew, selectMarks
    ))

    const onClickSelectMark = (mark: MT.IMark) => {
      controller.value.selectMarks([ mark ])
    }

    const mt = ref<MT.IMarkedText | null>(null)

    return {
      marksSelected,
      deselect, selectNew, selectMarks,
      controller,
      onClickSelectMark,
      mt
    }

  },

  created() {
    this.marks = this.initMarks()
  }

})

export default SubjectTest
</script>



<style scoped>

p {
  white-space: pre-wrap;
}

#mt {
  text-align: left;
  border: 5px solid black;
  margin-top: 30px;
  margin-bottom: 30px;
  margin-left: auto;
  margin-right: auto;
  padding: 10px 10px;
  border-radius: 10px;
  word-wrap: break-word;
  white-space: pre-wrap;
}

</style>

<style>

.mt-selection {
  background-color: brown;
  color: black;
}

</style>
