<script lang="ts" setup>
import { OnClickOutside } from '@vueuse/components';
import { useClipboard } from '@vueuse/core';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';

import { useCallbackStore, useCallbackActionsStore } from '~/store/callbackActions';
import { useDropdownStore } from '~/store/dropdown';
import { useReplaceRenewStore } from '~/store/replaceRenew';
import { useServerStore } from '~/store/server';
import { useThemeStore } from '~/store/theme';
import { useUpdateOsStore } from '~/store/updateOsActions';
import type { Server } from '~/types/server';
import 'tailwindcss/tailwind.css';
import '~/assets/main.css';

export interface Props {
  server?: Server | string;
}
const props = defineProps<Props>();

const { t } = useI18n();

const callbackStore = useCallbackStore();
const dropdownStore = useDropdownStore();
const replaceRenewCheckStore = useReplaceRenewStore();
const serverStore = useServerStore();
const updateOsStore = useUpdateOsStore();

const { callbackData } = storeToRefs(useCallbackActionsStore());
const { dropdownVisible } = storeToRefs(dropdownStore);
const {
  name,
  description,
  guid,
  keyfile,
  lanIp,
  osVersion,
  osVersionBranch,
  state,
  connectPluginInstalled,
} = storeToRefs(serverStore);
const { bannerGradient, theme, altTheme } = storeToRefs(useThemeStore());

const hideDropdown = computed(() => state.value === 'PRO' && !connectPluginInstalled.value);

/**
 * Close dropdown when clicking outside
 * @note If in testing you have two variants of the component on a page the clickOutside will fire twice making it seem like it doesn't work
 */
const clickOutsideTarget = ref();
const clickOutsideIgnoreTarget = ref();
const outsideDropdown = () => {
  if (dropdownVisible.value) { return dropdownStore.dropdownToggle(); }
};

/**
 * Copy LAN IP on server name click
 */
let copyIpInterval: string | number | NodeJS.Timeout | undefined;
const { copy, copied, isSupported } = useClipboard({ source: lanIp.value ?? '' });
const showCopyNotSupported = ref<boolean>(false);
const copyLanIp = () => { // if http then clipboard is not supported
  if (!isSupported || window.location.protocol === 'http:') {
    showCopyNotSupported.value = true;
    return;
  }
  copy(lanIp.value ?? '');
};
watch(showCopyNotSupported, (newVal, oldVal) => {
  if (newVal && oldVal === false) {
    clearTimeout(copyIpInterval);
    copyIpInterval = setTimeout(() => {
      showCopyNotSupported.value = false;
    }, 5000);
  }
});

/**
 * Sets the server store and locale messages then listen for callbacks
 */
onBeforeMount(() => {
  if (!props.server) {
    throw new Error('Server data not present');
  }

  if (typeof props.server === 'object') { // Handles the testing dev Vue component
    serverStore.setServer(props.server);
  } else if (typeof props.server === 'string') { // Handle web component
    const parsedServerProp = JSON.parse(props.server);
    serverStore.setServer(parsedServerProp);
  }

  // look for any callback params
  callbackStore.watcher();

  if (guid.value && keyfile.value) {
    if (callbackData.value) {
      return console.debug('Renew callback detected, skipping auto check for key replacement, renewal eligibility, and OS Update.');
    }
    // automatically check for replacement and renewal eligibility…will prompt user if eligible for a renewal / key re-roll for legacy keys
    replaceRenewCheckStore.check();

    // automatically check for OS updates for global notifications
    updateOsStore.checkForUpdate({
      cache: true,
      guid: guid.value,
      keyfile: keyfile.value,
      osVersion: osVersion.value,
      osVersionBranch: osVersionBranch.value, // if we're already on a non-stable release, include next
    });
  } else {
    console.warn('A valid keyfile and USB Flash boot device are required to check for key renewals, key replacement eligibiliy, and OS update availability.');
  }
});
</script>

<template>
  <div
    id="UserProfile"
    :class="{
      'text-alpha': !altTheme,
      'text-beta': altTheme,
    }"
    class="relative z-20 flex flex-col h-full gap-y-4px pt-4px pr-16px pl-40px"
  >
    <div v-if="bannerGradient" class="absolute z-0 w-[125%] top-0 bottom-0 right-0" :style="bannerGradient" />

    <div class="text-gamma text-10px xs:text-12px text-right font-semibold leading-normal relative z-10 flex flex-col items-end justify-end gap-x-4px xs:flex-row xs:items-baseline xs:gap-x-12px">
      <UpcUptimeExpire :t="t" />
      <span class="hidden xs:block">&bull;</span>
      <UpcServerState :t="t" />
    </div>

    <div class="relative z-10 flex flex-row items-center justify-end gap-x-16px h-full">
      <h1 class="text-14px sm:text-18px relative flex flex-col-reverse items-end md:flex-row border-0">
        <template v-if="description && theme?.descriptionShow">
          <span class="text-right text-12px sm:text-18px hidden 2xs:block">{{ description }}</span>
          <span class="text-gamma hidden md:inline-block px-8px">&bull;</span>
        </template>
        <button :title="t('Click to Copy LAN IP {0}', [lanIp])" class="opacity-100 hover:opacity-75 focus:opacity-75 transition-opacity" @click="copyLanIp()">
          {{ name }}
        </button>
        <span
          v-show="copied || showCopyNotSupported"
          class="text-white text-12px leading-none py-4px px-8px absolute top-full right-0 bg-gradient-to-r from-unraid-red to-orange text-center block rounded"
        >
          <template v-if="copied">{{ t('LAN IP Copied') }}</template>
          <template v-else>{{ t('LAN IP {0}', [lanIp]) }}</template>
        </span>
      </h1>

      <template v-if="!hideDropdown">
        <div class="block w-2px h-24px bg-gamma" />

        <OnClickOutside class="flex items-center justify-end h-full" :options="{ ignore: [clickOutsideIgnoreTarget] }" @trigger="outsideDropdown">
          <UpcDropdownTrigger ref="clickOutsideIgnoreTarget" :t="t" />
          <UpcDropdown ref="clickOutsideTarget" :t="t" />
        </OnClickOutside>
      </template>
    </div>
  </div>
</template>

<style lang="postcss">
@tailwind base;
@tailwind components;
@tailwind utilities;

.DropdownWrapper_blip {
  box-shadow: var(--ring-offset-shadow), var(--ring-shadow), var(--shadow-beta);

  &::before {
    @apply absolute z-20 block;

    content: '';
    width: 0;
    height: 0;
    top: -10px;
    right: 42px;
    border-right: 11px solid transparent;
    border-bottom: 11px solid var(--color-alpha);
    border-left: 11px solid transparent;
  }
}

.unraid_mark_2,
.unraid_mark_4 {
  animation: mark_2 1.5s ease infinite;
}
.unraid_mark_3 {
  animation: mark_3 1.5s ease infinite;
}
.unraid_mark_6,
.unraid_mark_8 {
  animation: mark_6 1.5s ease infinite;
}
.unraid_mark_7 {
  animation: mark_7 1.5s ease infinite;
}

@keyframes mark_2 {
  50% {
    transform: translateY(-40px);
  }
  100% {
    transform: translateY(0);
  }
}
@keyframes mark_3 {
  50% {
    transform: translateY(-62px);
  }
  100% {
    transform: translateY(0);
  }
}
@keyframes mark_6 {
  50% {
    transform: translateY(40px);
  }
  100% {
    transform: translateY(0);
  }
}
@keyframes mark_7 {
  50% {
    transform: translateY(62px);
  }
  100% {
    transform: translateY(0);
  }
}
</style>
