<template>
  <div id="dropZone" class="dropzone text-xs-semibold" :class="{ 'dropzone-hover': hover || dragOn }">
    <div v-if="dragOn" class="d-flex align-center">
      <v-icon class="minsk-500" icon="add" start />
      <span class="minsk-900 text-center">{{ t('texts.uploadDropText') }}</span>
    </div>
    <div v-else-if="hover" class="d-flex align-center">
      <v-icon class="minsk-500" icon="add" start />
      <span class="minsk-900 text-center">{{ t('texts.uploadHoverText') }}</span>
    </div>
    <div v-else class="d-flex align-center">
      <v-icon class="minsk-500" icon="add" start />
      <span class="minsk-900 text-center">{{ t('texts.uploadDefaultText') }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';

interface Props {
  height?: string;
}

const { t } = useI18n();

withDefaults(defineProps<Props>(), {
  height: '35vh'
});

type Emits = {
  onDropItems: [value: DragEvent];
  onClick: [value: Array<File>];
};

const emit = defineEmits<Emits>();

const hover = ref<boolean>(false);
const dragOn = ref<boolean>(false);
const droppedFiles = ref<boolean>(false);

onMounted(async () => {
  await nextTick();
  await registerDropZoneEvents();
});

async function registerDropZoneEvents() {
  const dropZone = document.getElementById('dropZone');
  if (!dropZone) return;

  registerEvents(
    dropZone,
    ['dragenter', 'dragover', 'dragleave', 'drop', 'mouseenter', 'mouseleave', 'mouseover', 'mouseup'],
    { handleEvent: stopPropagation }
  );
  registerEvents(dropZone, ['mouseenter', 'mouseover'], { handleEvent: onHover });
  registerEvents(dropZone, ['dragenter', 'dragover'], { handleEvent: onDragIn });
  registerEvents(dropZone, ['mouseleave', 'mouseup'], { handleEvent: onHoverLeave });
  registerEvents(dropZone, ['dragleave', 'drop'], { handleEvent: onDragOut });
  registerEvents(dropZone, ['drop'], { handleEvent: onDropItems });
  registerEvents(dropZone, ['mouseup'], { handleEvent: onClick });
}

function onDragIn(event: DragEvent): void {
  dragOn.value = true;
  event.dataTransfer!!.dropEffect = 'copy';
}

function onHover(_event: MouseEvent): void {
  hover.value = true;
}

function onHoverLeave(_event: MouseEvent): void {
  hover.value = false;
}

function onDragOut(_event: DragEvent): void {
  dragOn.value = false;
}

function onDropItems(event: DragEvent): void {
  droppedFiles.value = true;
  emit('onDropItems', event);
}

function onClick(_event: MouseEvent): void {
  droppedFiles.value = true;
  let input: HTMLInputElement = document.createElement('input');
  input.type = 'file';
  input.webkitdirectory = false;
  input.multiple = true;
  input.accept = 'application/vnd.ms-pki.stl';
  /* v8 ignore start */
  input.onchange = () => {
    let files = Array.from(input.files!!);
    emit('onClick', files);
  };
  /* v8 ignore stop */
  input.click();
}

function stopPropagation(event: DragEvent): void {
  event.preventDefault();
  event.stopPropagation();
}

function registerEvents(
  domElement: HTMLElement,
  eventList: Array<string>,
  listener: EventListenerOrEventListenerObject
) {
  for (const event of eventList) {
    domElement.addEventListener(event, listener);
  }
}

defineExpose({
  exposed: {
    dragOn,
    hover
  }
});
</script>

<style scoped>
#dropZone {
  cursor: pointer !important;
}

.dropzone {
  width: 248px;
  height: 40px;
  border: 1px dashed #d9d9de;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.dropzone-hover {
  background-color: #eff3fe;
  border-color: #6875ec;
}
</style>
