<template>
  <v-sheet class="mt-6" color="transparent" width="100%">
    <h5 class="text-h5 mb-4">Packages</h5>

    <v-sheet class="d-flex justify-space-between" color="transparent" width="100%">
      <v-sheet class="d-flex align-center w-50" color="transparent" style="gap: 15px">
        <v-text-field
          v-model="inputPkgBase"
          clearable
          color="primary"
          placeholder="Search Pkgbase"
          style="width: 30%; height: 60px"
          variant="outlined"></v-text-field>

        <v-select
          v-model="selectRepo"
          :items="selectRepoItems"
          color="primary"
          item-title="title"
          item-value="value"
          return-object
          single-line
          style="width: 30%; height: 60px"
          variant="outlined"></v-select>

        <v-select
          v-model="selectStatus"
          :items="selectStatusItems"
          color="primary"
          item-title="title"
          item-value="value"
          return-object
          single-line
          style="width: 30%; height: 60px"
          variant="outlined"></v-select>
      </v-sheet>

      <v-sheet
        class="d-flex align-center w-50 justify-end"
        color="transparent"
        style="height: 60px; transform: translateX(30px)">
        <v-pagination
          v-model="page"
          :length="pagesMax"
          active-color="primary"
          density="comfortable"
          style="width: 75%"
          variant="text"></v-pagination>
      </v-sheet>
    </v-sheet>

    <v-table class="mt-6" style="width: 100%; background: transparent">
      <thead>
        <tr>
          <th scope="col">Repository</th>
          <th scope="col">Pkgbase</th>
          <th scope="col">Status</th>
          <th scope="col">Reason</th>
          <th
            scope="col"
            title="link time optimization&#10;does not guarantee that package is actually built with LTO">
            LTO
          </th>
          <th scope="col" title="Debug-symbols available via debuginfod">DS</th>
          <th scope="col">Archlinux Version</th>
          <th scope="col">ALHP Version</th>
          <th class="text-end" scope="col" style="width: 30px">Info</th>
        </tr>
      </thead>

      <tbody id="main-tbody">
        <tr v-if="noPackagesFound">
          No Packages found
        </tr>
        <template v-else>
          <tr
            v-for="(pkg, index) in packages"
            :key="index"
            :style="`background-color: ${getStatus(pkg.status)};`">
            <td class="font-weight-bold">
              {{ pkg.repo.split('-')[0] }}
              <v-chip
                :color="getVersionColor(pkg.repo.split('-')[pkg.repo.split('-').length - 1])"
                class="ms-2"
                density="comfortable"
                label
                variant="flat">
                {{ pkg.repo.split('-')[pkg.repo.split('-').length - 1] }}
              </v-chip>
            </td>
            <td>{{ pkg.pkgbase }}</td>
            <td>{{ pkg.status.toLocaleUpperCase() }}</td>
            <td>{{ pkg.skip_reason || '' }}</td>
            <td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td>
            <td>
              <i
                :class="getDs(pkg.debug_symbols).class"
                :title="getDs(pkg.debug_symbols).title"></i>
            </td>
            <td>{{ pkg.arch_version }}</td>
            <td>{{ pkg.repo_version }}</td>
            <td class="d-flex align-center" style="gap: 3px; width: 60px">
              <a
                v-if="pkg.status === 'failed'"
                :href="`https://alhp.dev/logs/${pkg.repo.slice(pkg.repo.indexOf('-') + 1)}/${pkg.pkgbase}.log`"
                class="text-decoration-none"
                style="
                  color: darkgrey;
                  transform: translateY(-3px) translateX(-15px);
                  max-width: 15px;
                "
                target="_blank">
                <i class="fa fa-file-text fa-lg"></i>
              </a>
              <span v-else style="max-width: 15px"></span>
              <a
                :href="`https://archlinux.org/packages/?q=${pkg.pkgbase}`"
                class="text-decoration-none font-weight-bold"
                style="
                  color: darkgrey;
                  font-size: 18px;
                  padding: 0;
                  margin: 0;
                  width: 15px;
                  transform: translateX(-15px);
                "
                target="_blank"
                title="ArchWeb">
                AW
              </a>
              <span
                v-if="pkg.build_date && pkg.peak_mem"
                class="fa fa-info-circle fa-lg"
                style="color: darkgrey; transform: translateY(-1px); max-width: 15px !important">
                <v-tooltip activator="parent" location="start">
                  {{ `Built on ${pkg.build_date}` }}
                  <br />
                  {{ `Peak-Memory: ${pkg.peak_mem}` }}
                </v-tooltip>
              </span>
              <span v-else style="max-width: 15px !important"></span>
            </td>
          </tr>
        </template>
      </tbody>
    </v-table>
  </v-sheet>
</template>

<script lang="ts" setup>
import { onMounted, ref, UnwrapRef, watch } from 'vue'

interface Package {
  pkgbase: string
  repo: string
  split_packages: Array<string>
  status:
    | 'latest'
    | 'failed'
    | 'build'
    | 'skipped'
    | 'delayed'
    | 'building'
    | 'signing'
    | 'unknown'
    | 'queued'
  skip_reason: string
  lto: 'enabled' | 'unknown' | 'disabled' | 'auto_disabled'
  debug_symbols: 'available' | 'unknown' | 'not_available'
  arch_version: string
  repo_version: string
  build_date: string
  peak_mem: any
}

interface Packages {
  packages: Array<Package>
  total: number
  offset: number
  limit: number
}

const inputPkgBase = ref('')
const selectRepo = ref({ title: 'Repository (any)', value: 'any' })
const selectRepoItems = [
  { title: 'Repository (any)', value: 'any' },
  { title: 'core-x86-64-v2', value: 'core-x86-64-v2' },
  { title: 'extra-x86-64-v2', value: 'extra-x86-64-v2' },
  { title: 'multilib-x86-64-v2', value: 'multilib-x86-64-v2' },
  { title: 'core-x86-64-v3', value: 'core-x86-64-v3' },
  { title: 'extra-x86-64-v3', value: 'extra-x86-64-v3' },
  { title: 'multilib-x86-64-v3', value: 'multilib-x86-64-v3' },
  { title: 'core-x86-64-v4', value: 'core-x86-64-v4' },
  { title: 'extra-x86-64-v4', value: 'extra-x86-64-v4' },
  { title: 'multilib-x86-64-v4', value: 'multilib-x86-64-v4' }
]
const selectStatus = ref({ title: 'Status (any)', value: 'any' })
const selectStatusItems = [
  { title: 'Status (any)', value: 'any' },
  { title: 'Latest', value: 'latest' },
  { title: 'Built', value: 'built' },
  { title: 'Failed', value: 'failed' },
  { title: 'Skipped', value: 'skipped' },
  { title: 'Delayed', value: 'delayed' },
  { title: 'Queued', value: 'queued' },
  { title: 'Building', value: 'building' },
  { title: 'Signing', value: 'signing' },
  { title: 'Unknown', value: 'unknown' }
]

const page = ref(1)
const pagesMax = ref(1)
const packages = ref<Array<Package>>([])
const noPackagesFound = ref(false)

const searchPackages = (offset: number) => {
  const params = new URLSearchParams({
    limit: '50',
    offset: offset.toString()
  })

  if (inputPkgBase.value) params.append('pkgbase', inputPkgBase.value.toLowerCase())
  if (selectRepo.value.value !== 'any') params.append('repo', selectRepo.value.value)
  if (selectStatus.value.value !== 'any') params.append('status', selectStatus.value.value)

  fetch('https://api.alhp.dev/packages?' + params, {
    method: 'GET'
  })
    .then((response) => {
      if (response.ok) return response.json()
      if (response.status === 404) {
        noPackagesFound.value = true
        pagesMax.value = 1
      } else {
        throw new Error(response.statusText)
      }
    })
    .then((json) => {
      if (!json) return

      if (pagesMax.value !== json.total) {
        pagesMax.value = json.total / 50 + 1
      }

      packages.value = json.packages
    })
    .catch((error) => {
      console.error(error)
    })
}

const getVersionColor = (version: string) => {
  let color = 'grey'
  switch (version) {
    case 'v2':
      color = '#3498db'
      break
    case 'v3':
      color = '#f39c12'
      break
    case 'v4':
      color = '#2ecc71'
      break
  }
  return color
}

const getStatus = (status: UnwrapRef<Package['status']>) => {
  let color = ''
  switch (status) {
    case 'skipped':
      color = '#373737'
      break
    case 'queued':
      color = '#5d2f03'
      break
    case 'latest':
      color = ''
      break
    case 'failed':
      color = '#4f140f'
      break
    case 'signing':
      color = '#093372'
      break
    case 'building':
      color = '#084f46'
      break
    case 'unknown':
      color = '#191919'
      break
  }
  return color
}

const getLto = (lto: UnwrapRef<Package['lto']>) => {
  let icon = {
    title: '',
    class: ''
  }
  switch (lto) {
    case 'enabled':
      icon = {
        title: 'built with LTO',
        class: 'fa fa-check fa-lg text-success'
      }
      break
    case 'unknown':
      icon = {
        title: 'not built with LTO yet',
        class: 'fa fa-hourglass-o fa-lg text-grey'
      }
      break
    case 'disabled':
      icon = {
        title: 'LTO explicitly disabled',
        class: 'fa fa-times fa-lg text-red'
      }
      break
    case 'auto_disabled':
      icon = {
        title: 'LTO automatically disabled',
        class: 'fa fa-times-circle-o fa-lg text-amber'
      }
      break
  }
  return icon
}

const getDs = (ds: UnwrapRef<Package['debug_symbols']>) => {
  let icon = {
    title: '',
    class: ''
  }
  switch (ds) {
    case 'available':
      icon = {
        title: 'Debug symbols available',
        class: 'fa fa-check fa-lg text-success'
      }
      break
    case 'unknown':
      icon = {
        title: 'Not built yet',
        class: 'fa fa-hourglass-o fa-lg text-grey'
      }
      break
    case 'not_available':
      icon = {
        title: 'Not built with debug symbols',
        class: 'fa fa-times fa-lg text-red'
      }
      break
  }
  return icon
}

const url = new URL(window.location.href)

window.addEventListener('load', () => {
  inputPkgBase.value = url.searchParams.has('pkgbase')
    ? (url.searchParams.get('pkgbase') || '').toLowerCase()
    : ''
  selectRepo.value = {
    value: url.searchParams.has('repo')
      ? (url.searchParams.get('repo') || '').toLowerCase()
      : 'any',
    title: url.searchParams.has('repo')
      ? (url.searchParams.get('repo') || '').toLowerCase()
      : 'Repository (any)'
  }
  selectStatus.value = {
    value: url.searchParams.has('status')
      ? (url.searchParams.get('status') || '').toLowerCase()
      : 'any',
    title: url.searchParams.has('status')
      ? (url.searchParams.get('status') || '').substring(0, 1).toLocaleUpperCase() +
        (url.searchParams.get('status') || '')
          .substring(1, url.searchParams.get('status')!!.length - 1)
          .toLocaleUpperCase()
      : 'Status (any)'
  }

  searchPackages(0)
})

watch(
  () => page.value,
  () => {
    searchPackages(page.value)
  }
)

// @ts-ignore
let delayTimer = null
watch(
  () => inputPkgBase.value,
  () => {
    // @ts-ignore
    if (delayTimer) clearTimeout(delayTimer)
    delayTimer = setTimeout(function () {
      if (inputPkgBase.value) {
        url.searchParams.set('pkgbase', inputPkgBase.value.toLowerCase())
      } else {
        url.searchParams.delete('pkgbase')
      }
      window.history.pushState(null, '', url.toString())
      searchPackages(0)
    }, 250)
  }
)

watch(
  () => selectRepo.value,
  () => {
    if (selectRepo.value) {
      if (selectRepo.value.value === 'any') {
        url.searchParams.delete('repo')
      } else {
        url.searchParams.set('repo', selectRepo.value.value)
      }
      window.history.pushState(null, '', url.toString())
    }
    searchPackages(0)
  }
)

watch(
  () => selectStatus.value,
  () => {
    if (selectStatus.value) {
      if (selectStatus.value.value === 'any') {
        url.searchParams.delete('status')
      } else {
        url.searchParams.set('status', selectStatus.value.value)
      }
      window.history.pushState(null, '', url.toString())
    }
    searchPackages(0)
  }
)

onMounted(() => {
  searchPackages(0)
})
</script>
