/*
 * @Author: caoyp
 * @Email: caoyp@guahao.com
 * @Date: 2019-07-17 14:43:19
 * @Last Modified by: housy
 * @Last Modified time: 2020-03-26 15:44:08
 * @Description: 锚点定位组件
 */

<template>
    <div :style="{maxHeight: !isEmptyObj(tabConfig) ? `${contentWrapperHeight}` + 'px' : ''}"
         class="anchor-location-wrapper">
        <template v-if="!isEmptyObj(tabConfig)">
            <el-tabs
                v-if="tabConfig && tabConfig.tabs && tabConfig.tabs.length"
                v-model="tabConfig.activeName"
                @tab-click="handleClick"
                v-bind="tabConfig.extend"
                class="tabs">
                <template v-for="(item, index) in tabConfig.tabs">
                    <el-tab-pane
                        :label="item.label"
                        :name="item.name"
                        :key="index" />
                </template>
            </el-tabs>

            <div ref="contentBox" 
                 :style="{height: !isEmptyObj(tabConfig) ? `${contentWrapperHeight - tabWrapperHeight}` + 'px' : '',
                          overflowY: !isEmptyObj(tabConfig) ? 'auto' : 'initial', overflowX: 'hidden'}"
                 class="content-box">
                <!-- 内容区域自定义插槽 -->
                <slot />     
            </div>
        </template>
        <template v-else>
            <slot />
        </template>
    </div>
</template>

<script>
import { getUrlHash, isEmptyObj, debounce } from 'utils/util';
import { setTimeout } from 'timers';

const DelayTime = 200;
export default {
    name: 'BkAnchorLocationTag',
    props: {
        tabConfig: {
            required: true,
            type: Object,
            default: () => ({})
        }
    },
    data() {
        return {
            contentWrapperHeight: 0, // 表单容器的高度
            tabSaveArr: [], // 保存tab初始化距离窗口顶部的高度
            tabWrapperHeight: 0, // 初始化tab标签的高度
            tabActiveName: '' // 初始化tab高亮name
        };
    },
    watch: {
        tabConfig() {
            this.handleVisualHeightCalc();
        }
    },
    created() {
        if (this.tabConfig.history) {
            this.initTabs();
            this.$watch('$route.hash', (now, old) => {
                if (now === old) return;
                this.initTabs();
            });
        }
    },
    mounted() {
        // 初始化计算tab距离窗口顶部的高度
        if (this.tabConfig && Array.isArray(this.tabConfig.tabs)) {
            // 异步（待子组件完全挂载完毕之后再初始化计算高度）
            this.$nextTick(() => {
                // 获取可视化区域高度
                this.handleVisualHeightCalc();
                // 初始化计算容器滚动距离顶部的高度
                this.tabConfig.tabs.forEach(item => {
                    this.tabSaveArr.push({
                        name: item.name,
                        value: this.getInitTabHeight(item.name)
                    });
                });
            });
            // 监听content-box滚动
            this.scrollerEventHandler = debounce(this.handleContentBoxScroll, DelayTime);
            document.querySelector('.content-box').addEventListener('scroll', this.scrollerEventHandler, false);
        }
    },
    methods: {
        isEmptyObj,
        /**
         * 监听content-box可视化区域滚动
         */
        handleContentBoxScroll() {
            if (Array.isArray(this.tabSaveArr)) {
                this.tabSaveArr.forEach(item => {
                    if (item.value <= document.querySelector('.content-box').scrollTop) {
                        this.tabConfig.activeName = item.name;
                    }
                });
            }
        },

        /**
         * 可视化区域高度计算
         */
        handleVisualHeightCalc() {
            this.$nextTick(() => {
                // 获取内容区域元素
                const rightWrapperEle = document.querySelector('.right-wrapper');
                // 获取当前窗口的高度
                const windowWrapperHeight = window.innerHeight;
                // 获取内容区域距离容器顶部的高度
                const rightTopHeight = rightWrapperEle.getBoundingClientRect().top + window.pageYOffset;
                // 获取可视化区域的高度
                this.contentWrapperHeight = windowWrapperHeight - rightTopHeight;
                // 获取tab元素
                const tabWrapperEle = this.$el.querySelector('.tabs');
                // 获取tab的高度
                if (tabWrapperEle) this.tabWrapperHeight = tabWrapperEle.offsetHeight;
            });
        },

        /**
         * 获取点击tab滑动距离顶部的高度
         */
        getInitTabHeight(name) {
            const element = document.querySelector(`#${name}`);
            if (!element) return null;
            // 获取bk-title距离窗口顶部的高度
            const tabTopHeight = element.getBoundingClientRect().top + window.pageYOffset;
            // 获取content-box元素
            const formBoxEle = document.querySelector('.content-box');
            // 获取content-box元素滚动的距离
            const formBoxScrollTop = formBoxEle.scrollTop;
            // 获取content-box距离窗口顶部
            const formBoxTop = formBoxEle.getBoundingClientRect().top + window.pageYOffset;
            // 计算点击tab滑动距离窗口顶部的高度
            const calcTopHeight = tabTopHeight - formBoxScrollTop - (formBoxTop + window.pageYOffset);
            return calcTopHeight;
        },

        /**
         * 切换tab标签页模拟锚点定位
         * @param {string} name 设置tab的name值
         */
        handleClick(val) {
            // 滑动的对应title元素的位置
            const filterObj = this.tabSaveArr.find(item => item.name === val.name);
            document.querySelector('.content-box').removeEventListener('scroll', this.scrollerEventHandler);
            this.$nextTick(() => {
                const contentBoxEle = this.$refs.contentBox;
                if (filterObj.value !== null) {
                    contentBoxEle.scrollTop = filterObj.value;
                }
            });
            setTimeout(() => {
                document.querySelector('.content-box').addEventListener('scroll', this.scrollerEventHandler, false);
            }, 1000);
            this.$emit('toggled', val.name);
        },

        /**
         * tab初始化
         */
        initTabs() {
            const { tab } = getUrlHash();
            if (tab) {
                this.$emit('toggled', tab);
                this.tabConfig.activeName = tab;
            }
        }

    }
};
</script>