<template>
  <div class="bpmn-modeler">
    <div ref="container" class="bpmn-modeler__viewer" />
    <div ref="properties-panel" class="bpmn-modeler__properties-panel" />

    <div class="bpmn-modeler__toolbar">
      <button @click="openXmlDialog">
        XML
      </button>
    </div>

    <dialog ref="xmlDialog" class="bpmn-modeler__xml-dialog">
      <pre>{{ currentXml }}</pre>
    </dialog>
  </div>
</template>

<script lang="ts" setup>
import LintModule from 'bpmn-js-bpmnlint'
import BpmnModeler from 'camunda-bpmn-js/lib/camunda-platform/Modeler'
import { ref, shallowRef, useTemplateRef, watchEffect } from 'vue'
import I18nModule from '@/bpmn/modules/i18n'
import SdElementsModule from '@/bpmn/modules/service-desk'
import bpmnlintConfig from '@/bpmn/packed-lint-config'

const props = defineProps<{
  diagramXml: string
}>()

const containerRef = useTemplateRef('container')
const propertiesPanelRef = useTemplateRef('properties-panel')
const xmlDialogRef = useTemplateRef('xmlDialog')

const modeler = shallowRef<BpmnModeler>()

const currentXml = ref(props.diagramXml)

watchEffect(() => {
  if (modeler.value) {
    modeler.value.destroy()
    modeler.value = undefined
  }

  if (!containerRef.value || !propertiesPanelRef.value)
    return

  modeler.value = new BpmnModeler({
    container: containerRef.value,
    propertiesPanel: {
      parent: propertiesPanelRef.value,
    },
    additionalModules: [
      SdElementsModule,
      I18nModule,
      LintModule,
    ],
    linting: {
      bpmnlint: bpmnlintConfig,
    },
  })

  modeler.value.importXML(props.diagramXml)
})

async function openXmlDialog() {
  try {
    const { xml } = await modeler.value?.saveXML({ format: true })
    currentXml.value = xml

    xmlDialogRef.value?.showModal()
  }
  catch {}
}
</script>

<style lang="scss">
.bpmn-modeler {
  height: 100%;
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 350px;
  grid-template-rows: 1fr 30px;
  grid-template-areas: 'viewer properties' 'toolbar toolbar';

  &__viewer {
    grid-area: viewer;

    svg {
      outline: none;
    }
  }

  &__properties-panel {
    overflow-x: auto;
    grid-area: properties;
  }

  &__toolbar {
    grid-area: toolbar;
    background-color: lightgray;

    > button {
      height: 100%;
      border: none;
      outline: none;
      cursor: pointer;
    }
  }

  &__xml-dialog {
    width: 80%;
    max-height: 80%;
    outline: none;

    &::backdrop {
      backdrop-filter: blur(10px);
    }

    pre {
      white-space: pre-wrap;
      word-wrap: break-word;
    }
  }
}
</style>
