<template>
  <div ref="rowWrapper" class="row-wrapper"
    :draggable="!rename"
    @mouseup="onSelect($event)"
    @drop="onDrop($event)"
    @dragover="onDragOver($event)"
    @dragexit="onDragExit($event)"
    >

    <div class="row" :class="{ 'focused': item.focused, 'selected': item.selected, 'drop-target-active': dropTargetActive }">
      <div v-if="!visible" class="col icon"></div>
      <div v-if="!visible" class="col label"></div>

      <div v-if="visible" class="col icon">
        <img :src="item.previewUrl || item.icon" ref="iconImage" @error="iconError($event)"/>
        <i v-show="shareIndicatorProperty !== '' && !!item[shareIndicatorProperty]" class="fa-solid fa-share-nodes is-shared"></i>
      </div>

      <!-- this is just a placeholder label to allow the native browser search to work -->
      <div v-if="!visible">
        {{ item.name }}
      </div>
      <div v-else-if="visible && !rename" class="col label">
        <a v-show="item.href" class="open-action" @dblclick.stop @click="onOpen($event)" :href="item.href">{{ item.name }} {{ item.target ? `-> ${item.target}` : '' }}</a>
        <span v-show="!item.href">{{ item.name }} {{ item.target ? `→ ${item.target}` : '' }}</span>
      </div>
      <div v-else-if="visible && rename" ref="renameCell" class="col label rename">
        <TextInput
          ref="renameInput"
          v-model="newName"
          :disabled="renameBusy"
          @blur="onRenameEnd"
          @dblclick.stop
          @keydown.enter.stop="onRenameSubmit"
          @keydown.esc.stop="onRenameEnd"
          @keydown.stop
          />
      </div>

      <div v-if="visible && showStar" class="col star">
        <Icon :icon="`${item.star ? 'fa-solid' : 'fa-regular'} fa-star`" class="star-icon" :class="{ 'star-visible': item.star }" @dblclick.stop.prevent @click.stop.prevent="onToggleStar" />
      </div>
      <div v-if="visible && showOwner" class="col owner">{{ item.owner }}</div>
      <div v-if="visible && showSize" class="col size">{{ prettyFileSize(item.size) }}</div>
      <div v-if="visible && showModified" class="col modified" :title="item.modified.toLocaleString()">{{ prettyDate(item.modified) }}</div>
      <div v-if="visible" class="col actions">
        <div @mouseup.stop="onActionMenu($event)"><i class="fa-solid fa-ellipsis-vertical"/></div>
      </div>
    </div>
  </div>
</template>

<script setup>

import { ref, onMounted } from 'vue';

import { prettyDate, prettyFileSize } from '../utils.js';

import Icon from './Icon.vue';
import TextInput from './TextInput.vue';

const props = defineProps({
  item: Object,
  showOwner: {
    type: Boolean,
    default: false,
  },
  showSize: {
    type: Boolean,
    default: false,
  },
  showStar: {
    type: Boolean,
    default: false,
  },
  showModified: {
    type: Boolean,
    default: false,
  },
  shareIndicatorProperty: {
    type: String,
    default: '',
  },
  fallbackIcon: String,
  renameHandler: {
    type: Function,
    default() {
      console.warn('Missing renameHandler for DirectoryViewItem');
    },
  },
  starHandler: {
    type: Function,
    default() {
      console.warn('Missing starHandler for DirectoryViewItem');
    },
  },
  selectHandler: {
    type: Function,
    default() {
      console.warn('Missing selectHandler for DirectoryViewItem');
    },
  },
  dropHandler: {
    type: Function,
    default() {
      console.warn('Missing dropHandler for DirectoryViewItem');
    },
  },
  canDropHandler: {
    type: Function,
    default() {
      console.warn('Missing canDropHandler for DirectoryViewItem');
    },
  },
});

const emit = defineEmits(['activated', 'action-menu']);

const rowWrapper = ref(null);
const renameCell = ref(null);

const visible = ref(false);
const rename = ref(false);
const renameBusy = ref(false);
const newName = ref('');
const dropTargetActive = ref(false);
const previewRetries = ref(0);

function highlight() {
  rowWrapper.value?.classList.add('pankow-directory-view-highlight-animation');
  setTimeout(() => {
    rowWrapper.value?.classList.remove('pankow-directory-view-highlight-animation');
  }, 4000);
}

function onToggleStar() {
  props.starHandler(props.item);
}

function onActionMenu(event) {
  onSelect(event, true);
  emit('action-menu', props.item, event);
}

function onRenameBegin() {
  rename.value = true;
  newName.value = props.item.name;

  setTimeout(() => {
    const elem = renameCell.value?.querySelector('input.pankow-text-input');
    if (!elem) return;

    elem.focus();

    if (typeof elem.selectionStart !== 'undefined') {
      elem.selectionStart = 0;
      elem.selectionEnd = props.item.name.lastIndexOf('.');
    }
  }, 0);
}

function onRenameEnd() {
  rename.value = false;
  renameBusy.value = false;
  newName.value = '';
}

async function onRenameSubmit() {
  if (!newName.value) return;

  renameBusy.value = true;
  await props.renameHandler(props.item, newName.value);
  onRenameEnd();
}

function onOpen(event) {
  if (event.ctrlKey || event.metaKey) return;

  event.preventDefault();
  event.stopPropagation();

  emit('activated', props.item);
}

function onSelect(event, actionMenu = false) {
  if ((event.button === 2 || actionMenu) && event.ctrlKey) {
    props.selectHandler(props.item, event, true);
  } else {
    props.selectHandler(props.item, event);
  }
}

function onDrop(event) {
  if (!props.canDropHandler(props.item)) return;

  event.stopPropagation();

  props.dropHandler(props.item, event);
  dropTargetActive.value = false;
}

function onDragOver(event) {
  if (!props.canDropHandler(props.item)) return;

  event.preventDefault();
  event.stopPropagation();

  event.dataTransfer.dropEffect = 'move';
  dropTargetActive.value = true;
}

function onDragExit() {
  if (!props.item.isDirectory) return;

  dropTargetActive.value = false;
}

function iconError(event) {
  event.target.src = props.fallbackIcon;

  setTimeout(() => {
    if (previewRetries.value > 5) return;
    previewRetries.value += 1;

    event.target.src = props.item.previewUrl || props.item.icon;
  }, 1000);
}

onMounted(() => {
  const el = rowWrapper.value;
  if (!el) return;

  const observer = new IntersectionObserver((result) => {
    if (result[0].isIntersecting) {
      visible.value = true;
      observer.unobserve(el);
    }
  });

  observer.observe(el);
});

defineExpose({
  highlight,
  onRenameBegin,
  get $el() {
    return rowWrapper.value;
  },
});

</script>

<style scoped>

.row-wrapper {
  --background-color-hover: #ededed;
  --background-color-selected: #dbedfb;
  --border-color-focus: #b3cfe5;
}

@media (prefers-color-scheme: dark) {
  .row-wrapper {
    --background-color-hover: rgba(255, 255, 255, 0.1);
    --background-color-selected: rgba(255, 255, 255, 0.2);
    --border-color-focus: rgba(255, 255, 255, 0.3);
  }
}

.row-wrapper {
  width: 100%;
  padding: 2px 0;
  margin-bottom: 5px;
}

.row {
  display: flex;
  overflow: hidden;
  width: 100%;
  border-radius: 3px;
  transition: all 100ms;
  border: 2px solid transparent;
}

.row-wrapper:hover > .row {
  background-color: var(--background-color-hover);
}

.row.drop-target-active {
  border: 2px solid var(--pankow-color-primary);
}

.row.selected {
  background-color: var(--background-color-selected) !important;
}

.row.focused {
  border: solid 2px var(--border-color-focus);
}

.col {
  white-space: nowrap;
}

.icon {
  height: 45px;
  width: 45px;
  padding: 5px;
}

.icon > img {
  width: 35px;
  height: 35px;
  object-fit: cover;
}

.star-icon {
  color: #ffcb00;
  visibility: hidden;
  cursor: pointer;
}

.star-icon:hover {
  transform: scale(1.5);
  transform-origin: center center;
}

.row.focused .star-icon,
.row.selected .star-icon,
.row-wrapper:hover > .row .star-icon {
  visibility: visible;
}

.star-visible {
  visibility: visible !important;
}

.is-shared {
  position: relative;
  right: 13px;
  bottom: 0;
  font-size: 1.2rem
}

.label {
  padding-left: 5px;
  flex-grow: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: auto;
  display: flex;
}

.label > button {
  display: none;
  margin: auto 10px;
}

.label:hover > button {
  display: block;
}

.label.rename > button {
  display: block;
}

.size {
  width: 100px;
  margin: auto;
}

.star {
  width: 80px;
  margin: auto;
  text-align: center;
}

.owner {
  width: 100px;
  margin: auto;
}

.modified {
  width: 100px;
  margin: auto;
}

.actions {
  display: flex;
  margin: auto;
  margin-right: 10px;
}

.actions > div {
  padding: 0 10px;
  cursor: pointer;
}

.open-action {
  cursor: pointer;
}

.open-action:hover {
  text-decoration: underline;
}


</style>

<style>

.pankow-directory-view-highlight-animation {
  animation: pankow-directory-view-highlight-animation-breath 0.8s 4;
}

@keyframes pankow-directory-view-highlight-animation-breath {
  0% {
    opacity: 1;
  }

  50% {
    opacity: 0.5;
  }

  100% {
    opacity: 1;
  }
}

</style>
