<!-- 图例组件 -->

<script setup lang="ts">
    import { isArray } from 'lodash-es'
    import { createReusableTemplate } from '@vueuse/core'
    import type { Option } from './types'
    import { deepMerge } from '@/utils'
    import { cssAdditionCalc } from '@/components/Map/Widgets/utils'

    const props = defineProps({
        // 显示
        show: {
            type: Boolean,
            default: true,
        },
        // 展开
        expand: {
            type: Boolean,
            default: false,
        },
        // 标题
        title: {
            type: String,
        },
        // 底部距离 rpx
        bottom: {
            type: Number,
            default: 0,
        },
        // JSON 数据
        option: {
            type: Object as PropType<Option>,
            default: () => ({}) as Option,
        },
    })

    const emits = defineEmits(['register'])

    // 定义复用渲染组件
    const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{ item: Recordable; sub?: boolean }>()

    const positionBottom = computed(() => cssAdditionCalc(30, data.bottom))
    const data = reactive({
        show: props.show,
        expand: props.expand,
        title: props.title,
        option: props.option,
        bottom: props.bottom,
    })

    function setTitle(title: string) {
        data.title = title
    }

    function setOption(option: Option) {
        data.option = option
    }

    function toggleShow(show?: boolean) {
        data.show = show ?? !data.show
    }

    function toggleExpand(expand?: boolean) {
        data.expand = expand ?? !data.expand
    }

    function setProps(value: Partial<typeof props>) {
        deepMerge(data, value)
    }

    function getProp(key: keyof typeof props) {
        return data[key]
    }

    emits('register', {
        setProps,
        getProp,
        setTitle,
        setOption,
        toggleShow,
        toggleExpand,
    })

    function getBorderColor(color: string) {
        switch (color) {
            case 'white':
            case '#fff':
            case '#ffffff':
            case '#FFFFFF':
            case 'rgb(255, 255, 255)':
            case 'rgba(255, 255, 255, 1)':
                return '#d7d7d7'
            default:
                return color
        }
    }
</script>

<template>
    <view class="wrap legend flex-center" @click="data.expand = !data.expand" v-show="data.show">
        <!-- 展开/收起 -->
        <view class="expand-action flex-center" v-show="!data.expand">
            <view class="text">图例</view>
            <Icon icon="ic-round-keyboard-arrow-up" color="#1890ff" size="42" />
        </view>

        <!-- 内容 -->
        <view class="expand-content flex-center" v-show="data.expand">
            <!-- 标题 -->
            <view v-if="data.title" class="title">{{ data.title }}</view>

            <!-- 定义复用渲染组件 -->
            <DefineTemplate v-slot="{ item, sub }">
                <view class="item">
                    <!-- 图标 -->
                    <view v-if="item.icon" class="icon flex-center">
                        <CacheImage :src="item.icon" width="34" height="34" background="transparent" />
                    </view>

                    <!-- 色块 -->
                    <view
                        v-if="item.color"
                        class="color"
                        :style="{
                            backgroundColor: item.color,
                            border: `1rpx solid ${getBorderColor(item.color)}`,
                            ...data.option.blockStyle,
                        }"
                    />

                    <!-- 标签 -->
                    <view
                        v-if="String(item.label)"
                        class="label"
                        :class="{ 'color-label': item.color }"
                        :style="!sub && { ...data.option.labelStyle }"
                    >
                        {{ item.label }}
                    </view>

                    <!-- 子项集合 -->
                    <view v-if="item.items" class="sub-items">
                        <view v-for="(subItem, index) in item.items" :key="index" class="item">
                            <ReuseTemplate :item="subItem" :sub="true" />
                        </view>
                    </view>
                </view>
            </DefineTemplate>

            <!-- JSON -->
            <view class="option">
                <template v-if="isArray(data.option.items?.[0])">
                    <view v-for="(item, index) in data.option.items" :key="index" class="item-wrap">
                        <view v-for="(subItem, subIndex) in item" :key="subIndex" class="items">
                            <ReuseTemplate :item="subItem" />
                        </view>
                    </view>
                </template>

                <template v-else>
                    <view class="item-wrap">
                        <view v-for="(item, index) in data.option.items" :key="index" class="items">
                            <ReuseTemplate :item="item" />
                        </view>
                    </view>
                </template>
            </view>
        </view>
    </view>
</template>

<style lang="scss" scoped>
    @use '../../common.scss' as *;

    .wrap {
        @include animate();

        position: absolute;
        left: 30rpx;
        bottom: v-bind(positionBottom);
        z-index: 99;
    }

    .legend {
        flex-direction: column;
        padding: 12rpx 20rpx;
        background-color: #fff;
        border-radius: 10rpx;
        box-shadow: 0 0 15rpx rgba(0, 0, 0, 0.2);

        .expand-action {
            font-size: 26rpx;
            font-weight: bold;
            color: #1890ff;

            .text {
                margin-right: 6rpx;
            }
        }

        .expand-content {
            flex-direction: column;
            font-size: 24rpx;
            color: #555;

            .title {
                margin-bottom: 15rpx;
                font-weight: bold;
            }

            .option {
                display: flex;

                .item-wrap {
                    + .item-wrap {
                        margin-left: 15rpx;
                    }

                    .item {
                        display: flex;
                        align-items: center;
                        justify-content: flex-start;

                        .icon {
                            margin-right: 8rpx;
                            padding: 4rpx;
                        }

                        .color {
                            width: 42rpx;
                            height: 24rpx;
                            margin-right: 10rpx !important;
                        }

                        .label {
                            color: #777;
                            letter-spacing: 1px;
                            white-space: pre-wrap;
                            text-align: center;

                            &.color-label {
                                height: 24rpx;
                            }
                        }
                    }

                    .sub-items {
                        display: flex;

                        .item {
                            flex-direction: column;
                            justify-content: center;
                            margin: 2rpx 5rpx;
                            font-size: 20rpx;
                        }
                    }
                }
            }
        }
    }
</style>
