<script setup>
import { types as redisTypes } from '@/consts/support_redis_type.js'
import ContentValueString from '@/components/content_value/ContentValueString.vue'
import ContentValueHash from '@/components/content_value/ContentValueHash.vue'
import ContentValueList from '@/components/content_value/ContentValueList.vue'
import ContentValueSet from '@/components/content_value/ContentValueSet.vue'
import ContentValueZset from '@/components/content_value/ContentValueZSet.vue'
import ContentValueStream from '@/components/content_value/ContentValueStream.vue'
import { useThemeVars } from 'naive-ui'
import useBrowserStore from 'stores/browser.js'
import { computed, onMounted, ref, watch } from 'vue'
import { isEmpty } from 'lodash'
import useDialogStore from 'stores/dialog.js'
import { useI18n } from 'vue-i18n'
import ContentToolbar from '@/components/content_value/ContentToolbar.vue'
import ContentValueJson from '@/components/content_value/ContentValueJson.vue'
import { isMacOS } from '@/utils/platform.js'

const themeVars = useThemeVars()
const browserStore = useBrowserStore()
const dialogStore = useDialogStore()

const props = defineProps({
    blank: Boolean,
    content: {
        type: Object,
        default: {},
    },
})
const i18n = useI18n()

/**
 *
 * @type {ComputedRef<{
 *      type:
 *      String, name: String,
 *      db: Number,
 *      keyPath: String,
 *      keyCode: Array,
 *      ttl: Number,
 *      value: [String, Object],
 *      size: Number,
 *      length: Number,
 *      format: String,
 *      decode: String,
 *      end: Boolean
 *      loading: Boolean
 * }>}
 */
const data = computed(() => {
    return props.content
})
const initializing = ref(false)

const loading = computed(() => {
    return data.value.loading === true || initializing.value
})

const binaryKey = computed(() => {
    return !!data.value.keyCode
})

const valueComponents = {
    [redisTypes.STRING]: ContentValueString,
    [redisTypes.HASH]: ContentValueHash,
    [redisTypes.LIST]: ContentValueList,
    [redisTypes.SET]: ContentValueSet,
    [redisTypes.ZSET]: ContentValueZset,
    [redisTypes.STREAM]: ContentValueStream,
    [redisTypes.JSON]: ContentValueJson,
}

const keyName = computed(() => {
    return !isEmpty(data.value.keyCode) ? data.value.keyCode : data.value.keyPath
})

/**
 *
 * @param {boolean} reset
 * @param {boolean} [full]
 * @param {string} [selMatch]
 * @return {Promise<void>}
 */
const loadData = async (reset, full, selMatch) => {
    try {
        if (!!props.blank) {
            return
        }
        const { name, db, matchPattern } = data.value
        reset = reset === true
        await browserStore.loadKeyDetail({
            server: name,
            db: db,
            key: keyName.value,
            matchPattern: selMatch === undefined ? matchPattern : selMatch,
            decode: '',
            format: '',
            reset,
            full: full === true,
        })
    } finally {
    }
}

/**
 * reload current key
 * @param {string} [selDecode]
 * @param {string} [selFormat]
 * @return {Promise<void>}
 */
const onReload = async (selDecode, selFormat) => {
    try {
        const { name, db, keyCode, keyPath, decode, format, matchPattern } = data.value
        const targetFormat = selFormat || format
        const targetDecode = selDecode || decode
        browserStore.setSelectedFormat(name, keyPath, db, targetFormat, targetDecode)
        await browserStore.reloadKey({
            server: name,
            db,
            key: keyCode || keyPath,
            decode: targetDecode,
            format: targetFormat,
            matchPattern,
            showLoading: false,
        })
    } finally {
    }
}

const onKeyShortcut = (e) => {
    // console.log(e)
    switch (e.key) {
        case 'Delete':
            onDelete()
            return

        case 'd':
            if (e.metaKey) {
                onDelete()
            }
            return

        case 'F5':
            onReload()
            return

        case 'r':
            if (e.metaKey && isMacOS()) {
                onReload()
            }
            return

        case 'F2':
            onRename()
            return
    }
}

const onRename = () => {
    const { name, db, keyPath } = data.value
    if (binaryKey.value) {
        $message.error(i18n.t('dialogue.rename_binary_key_fail'))
    } else {
        dialogStore.openRenameKeyDialog(name, db, keyPath)
    }
}

const onDelete = () => {
    $dialog.warning(i18n.t('dialogue.remove_tip', { name: data.value.keyPath }), () => {
        const { name, db } = data.value
        browserStore.deleteKey(name, db, keyName.value).then((success) => {
            if (success) {
                $message.success(i18n.t('dialogue.delete.success', { key: data.value.keyPath }))
            }
        })
    })
}

const onLoadMore = () => {
    loadData(false, false)
}

const onLoadAll = () => {
    loadData(false, true)
}

const onMatch = (match) => {
    loadData(true, false, match || '')
}

const contentRef = ref(null)
const initContent = async () => {
    // onReload()
    try {
        initializing.value = true
        if (contentRef.value?.reset != null) {
            contentRef.value?.reset()
        }
        await loadData(true, false, '')
    } finally {
        initializing.value = false
    }
}

onMounted(() => {
    // onReload()
    initContent()
})

watch(() => data.value?.keyPath, initContent)
</script>

<template>
    <n-empty v-if="props.blank" :description="$t('interface.nonexist_tab_content')" class="empty-content">
        <template #extra>
            <n-button :focusable="false" @click="onReload">{{ $t('interface.reload') }}</n-button>
        </template>
    </n-empty>
    <!-- FIXME: keep alive may cause virtual list null value error. -->
    <!-- <keep-alive v-else> -->
    <component
        tabindex="0"
        @keydown="onKeyShortcut"
        :is="valueComponents[data.type]"
        v-else
        ref="contentRef"
        :db="data.db"
        :decode="data.decode"
        :end="data.end"
        :format="data.format"
        :key-code="data.keyCode"
        :key-path="data.keyPath"
        :length="data.length"
        :loading="loading"
        :name="data.name"
        :size="data.size"
        :ttl="data.ttl"
        :value="data.value"
        @delete="onDelete"
        @loadall="onLoadAll"
        @loadmore="onLoadMore"
        @match="onMatch"
        @reload="onReload">
        <template #toolbar>
            <content-toolbar
                :db="data.db"
                :key-code="data.keyCode"
                :key-path="data.keyPath"
                :key-type="data.type"
                :loading="loading"
                :server="data.name"
                :ttl="data.ttl"
                class="value-item-part"
                @delete="onDelete"
                @reload="onReload"
                @rename="onRename" />
        </template>
    </component>
    <!--    </keep-alive>-->
</template>

<style lang="scss" scoped></style>
