import debounce from 'lodash/debounce'
import { Messager } from '../../../core/src/component/msgDistribute'
import { fetch } from '../../../core/src/component/httpClient'
import INTERFACE from '../const/INTERFACE'
import tool from '../utils/tool'
import { FloorChannelType} from '../const'
import floorManager from '../common/FloorManager'
let isReactRendering = false
let isWaiting = false
export default class MiddlePreview {
    element: HTMLElement
    content: string = ''
    iframeDocument: any
    layoutContainer: HTMLElement
    isIframeLoaded: boolean
    constructor(element: HTMLElement, iframeUrl: string = '//isvdev.jd.com/iframe#/pages/iframe/index') {
        const that = this
        this.content = `<iframe src="${iframeUrl}" onload="window.top.isvIframeOnload()" frameBorder="none" style="width: 375px; min-height: 800px; margin: 0 auto;box-shadow: 0 0 10px 0 rgb(0 0 0 / 10%);"></iframe>`
        isWaiting = false
        this.element = element
        this.isIframeLoaded = false
        const onresize = ()=>{
            this.resizeIframe()
        }
        window.addEventListener("resize", debounce(onresize, 300))
        window.top.isvIframeOnload = (e)=>{
            this.isIframeLoaded = true
            this.updateStyle()
        }
        this.element.innerHTML = this.content
        this.bindMessager()
    }
    updateStyle() {
        setTimeout(()=>{
            this.resizeIframe()
        }, 200)
    }
    resizeIframe() {
        if(!this.isIframeLoaded){
            return
        }
        const [iframeDoc, iframeNode] = tool.getIframeInfo()
		if (iframeNode && iframeDoc) {
			let scrollHeight = iframeDoc.body.scrollHeight
            let sh = scrollHeight
            let remainScreenHeight = document.body.clientHeight - 77 
			let height = Math.max(sh, remainScreenHeight) + "px"
            iframeNode.style.height = height
		}
	}
    
    async renderFloors() {
        const floorDatas = await this.getDecorateContentData()
        if (floorDatas) {
            floorManager.renderAllFloors(floorDatas, () => {
                this.bindEvent()
                this.updateStyle()
                this.autoFocusFloor()
            })
        }
    }
    
    autoFocusFloor() {
        const [iframeDoc] = tool.getIframeInfo()
        if (iframeDoc) {
            const firstFloor = iframeDoc.querySelector(".J_container")
            const input = firstFloor.querySelector(`[value^="container_"]`);
            let containerId = input?.value?.substring(10);
            if(containerId==''){
                return
            }
            if (containerId == '0') {
                const nextTempDoc = firstFloor.nextElementSibling
                if (nextTempDoc.querySelector(`[value^="container_"]`)) {
                    $(nextTempDoc).trigger("click");
                } else {
                    return
                }
            } else {
                $(firstFloor).trigger("click");
            }
        }
    }
    bindMessager() {
        Messager.on('iframeDidRender', (req) => {
            this.renderFloors()
        })
        
        Messager.on('focusModule', (req, res) => {
            const {containerId, openConfig = true} = req
            isWaiting = false;     
            const activeContainerId = floorManager.getActiveContainerId()
            if(containerId && containerId == activeContainerId){
                return
            }
            const curContainerId = containerId || floorManager.getActiveContainerId()
            this.selectFloor(curContainerId)
            openConfig && Messager.trigger('openConfig', {
                containerId: req.containerId,
            })
        })
        Messager.on('clearDecPlaceholder', () => {
            window.top.dragoverFloorId = '';    
            this.clearPlaceHolder(() => {
                this.updateStyle()
            })
        })
        Messager.on('addModule', (req) => {
            const preFloorId = req.preFloorId
            const floorData = req.floor
            if(!floorData){
                return
            }
            let newFloorId = floorData.containers[0].containerId;
            floorManager.addFloor(floorData, preFloorId, () => {
                this.bindEvent()
                this.updateStyle()
                Messager.trigger("focusModule", {
                    containerId: newFloorId,
                });
            })
        })
        Messager.on('updateModuleData', (req) => {
            const floorData = req.floor
            if(!floorData){
                return
            }
            let newFloorId = floorData.containers[0].containerId;
            floorManager.updateFloor(floorData, () => {
                this.updateStyle()
                this.selectFloor(newFloorId);
            })
        })
        Messager.on('deleteFloor', (req) => {
            const {curFloorId} = req
            floorManager.deleteFloor(curFloorId, (nextContainerId)=>{
                this.updateStyle()
                if(nextContainerId!=0){
                    Messager.trigger("focusModule", {
                        containerId: nextContainerId,
                    });
                }
                else{
                    Messager.trigger("hideModuleBar")
                    Messager.trigger("closeConfig")
                }
            })
        })
        Messager.on('moveFloor', (req) => {
            const {curFloorId, preFloorId} = req
            floorManager.moveFloor(curFloorId, preFloorId, (curFloorId)=>{
                this.updateStyle()
                Messager.trigger("focusModule", {
                    containerId: curFloorId,
                    openConfig: false
                });
            })
        })
    }
    
    clearPlaceHolder(callback = null) {
        tool.sendMessage2App({ code: 'clearPlaceHolder', data: null }, callback)
    }
    
    selectFloor(containerId, callback = null) {
        floorManager.setActiveContainerId(containerId)
        tool.sendMessage2App({
            code: 'selectFloor', data: {
                containerId
            }
        }, callback)
    }
    
    setPlaceHolder(preFloorId) {
        if (window.top.dragoverFloorId !== preFloorId && isReactRendering === false) {
            window.top.dragoverFloorId = preFloorId;
            isReactRendering = true;
            tool.sendMessage2App({
                code: 'setPlaceHolder', data: {
                    preContainerId: preFloorId
                }
            }, () => {
                isReactRendering = false;
                this.updateStyle()
            })
        }
    }
    
    getDecorateContentData() {
        return fetch({ url: INTERFACE.floorContent }).then((data) => {
            if (data && data.code == 200 && data.data) {
                return data.data
            }
        }).catch((e) => {
            return null
        })
    }
    
    
    getFloorNodeById(containerId) {
        let dom = document.querySelector(`[value="container_${containerId}"]`);
        if (dom) {
            return dom.parentNode;
        } else {
            return null;
        }
    }
    
    resetCanvasPosition(containerId) {
        const $module = $(this.getFloorNodeById(containerId));
        const scrollTop = $module.position().top;
        const moduleTop = $module[0].getBoundingClientRect().top;
        const canvasScrollTop = window.top.document.querySelector('.J_editorInstanceArea').scrollTop;
        const canvasHeight = $(window.top).height() - $(window.top.document.querySelector('.J_decoTopBar')).height();
        if (
            (moduleTop < canvasScrollTop) ||
            (canvasScrollTop + canvasHeight < moduleTop)
        ) {
            Messager.trigger('positionContainer', {
                scrollTop,
            })
        }
    }
    
    getContainerId(e) {
        const containerDom = e?.target?.closest('.J_container')
        let input = containerDom?.querySelector(`[value^="container_"]`)
        let containerId = ''
        if (input) {
            containerId = input.value.substring(10)
        }
        return containerId
    }
    click = (e) => {
        e.preventDefault();
        e.stopPropagation();
        const containerId = this.getContainerId(e)
        if (containerId != '') {
            if (isWaiting || containerId == '0') {
                isWaiting = false
                return;
            }
            isWaiting = true;
            Messager.trigger('focusModule', {
                containerId,
            });
        }
    }
    dragover = (e) => {
        e.preventDefault();
        e.stopPropagation();
        const containerId = this.getContainerId(e)
        if (containerId != '') {
            this.setPlaceHolder(containerId);
        }
        else{
            const lastContainerId = floorManager.getLastContainerId()
            this.setPlaceHolder(lastContainerId);
        }
    }
    
    drop = (e) => {
        e.preventDefault();
        e.stopPropagation();
        Messager?.trigger('clearDecPlaceholder')
        let containerId = this.getContainerId(e)
        if (containerId == '') {
            containerId = floorManager.getLastContainerId()
        }
        const moduleId = e.dataTransfer.getData('moduleId')
        const moduleDataStr = e.dataTransfer.getData('moduleData')
        const moduleData = JSON.parse(moduleDataStr)
        if (moduleId && moduleData) {
            let data = {
                moduleId: moduleId,
                preFloorId: containerId,
                moduleType: moduleData?.moduleType || FloorChannelType.ISV
            }
            fetch({ url: INTERFACE.renderModule, data }).then((data) => {
                if (data && data.code == 200) {
                    Messager.trigger('addModule', {
                        floor: data.data,
                        moduleId,
                        moduleData,
                        preFloorId: containerId
                    })
                }
            }).catch(e => {
                console.log(e)
                return null
            })
        }
    }
    
    dragleave = (e) => {
        if(!this.layoutContainer){
            return
        }
        let width = this.layoutContainer.offsetWidth;
        let height = this.layoutContainer.offsetHeight;
        let {clientX, clientY, layerX, layerY} = e;
        if(clientX <= 0 || clientY <= 0 || clientX >= width || clientY >= height){
            Messager.trigger('clearDecPlaceholder');
        }
    }
    bindEvent(): void {
        const [iframeDoc] = tool.getIframeInfo()
        this.layoutContainer = iframeDoc && iframeDoc.getElementById('app')
        if (!this.layoutContainer) {
            return
        }
        this.layoutContainer.removeEventListener('click', this.click);
        this.layoutContainer.addEventListener('click', this.click, false);
        this.layoutContainer.removeEventListener('dragover', this.dragover);
        this.layoutContainer.addEventListener('dragover', this.dragover, false);
        this.layoutContainer.removeEventListener('drop', this.drop);
        this.layoutContainer.addEventListener('drop', this.drop, false);
        this.layoutContainer.removeEventListener('dragleave', this.dragleave);
        this.layoutContainer.addEventListener('dragleave', this.dragleave, false);
    }
    
    render(): void {
        this.element.style.visibility = 'visible'
    }
}