import * as React from 'react';
import { useRef } from 'react';
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import type { IDialogChildProps } from '..';
import { offset } from '../../util';
import MemoChildren from './MemoChildren';
import { Spin } from 'antd'
import { RadiusBottomrightOutlined } from '@ant-design/icons'
import { v4 as uuidv4 } from 'uuid';
import "../../style/index.less"
const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' };

export type ContentProps = {
    // motionName: string;
    // ariaId: string;
    // onVisibleChanged: (visible: boolean) => void;
    // onMouseDown: React.MouseEventHandler;
    // onMouseUp: React.MouseEventHandler;
    // dragable: boolean;
    // resizable: boolean;
    // autoResetWhenReOpen: boolean;
    // autoCenterWhenReOpen: boolean;
    // onResize:()=>{};
    [propName: string]: any;
} & IDialogChildProps

export type ContentRef = {
    focus: () => void;
    changeActive: (next: boolean) => void;
}
const id = uuidv4()
const Content = React.forwardRef<ContentRef, ContentProps>((props, ref) => {
    const {
        closable,
        prefixCls,
        width,
        height,
        footer,
        title,
        closeIcon,
        style,
        className,
        visible,
        forceRender,
        bodyStyle,
        bodyProps,
        children,
        destroyOnClose,
        modalRender,
        motionName,
        ariaId,
        onClose,
        onVisibleChanged,
        onMouseDown,
        onMouseUp,
        mousePosition,
        dragable,
        resizable,
        autoResetWhenReOpen,
        autoCenterWhenReOpen,
        onResize,
        reszieMinWidth = 0,
        reszieMinHeight = 0,
    } = props;
    // console.log("---props---",props)
    const sentinelStartRef = useRef<HTMLDivElement>();
    const sentinelEndRef = useRef<HTMLDivElement>();
    const dialogRef = useRef<HTMLDivElement>();
    const MULTIPLE = 1;

    let resizeStartClientX = 0; // resize事件发生时的应用客户端区域的x坐标
    let resizeStartClientY = 0; // resize事件发生时的应用客户端区域的y坐标
    let isDragResize = false;
    let isDrag = false;
    let dragStartPageX = 0; // drag事件发生时相对于整个文档的x（水平）坐标
    let dragStartPageY = 0; // drag事件发生时相对于整个文档的x（垂直）坐标
    let leftOffset = 0;
    let topOffset = 0;
    let clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
    let clientHeight = document.documentElement.clientHeight || document.body.clientHeight;

    window.addEventListener('resize', () => {
        clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
        clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
        isDrag = false;
        isDragResize = false;
        autoCenter();
    });


    // ============================== Ref ===============================
    React.useImperativeHandle(ref, () => ({
        focus: () => {
            sentinelStartRef.current?.focus();
        },
        changeActive: (next) => {
            const { activeElement } = document;
            if (next && activeElement === sentinelEndRef.current) {
                sentinelStartRef.current.focus();
            } else if (!next && activeElement === sentinelStartRef.current) {
                sentinelEndRef.current.focus();
            }
        },
    }));
    //============声明弹框宽高及位置数值=====================
    const [transformOrigin, setTransformOrigin] = React.useState<string>();
    const [positonStyle, setPositionStyle] = React.useState({
        width: parseInt(width + ""),
        height: parseInt(height + ""),
        left: (clientWidth - parseInt(width + "")) / 2,
        top: (clientHeight - parseInt(height + "")) / 2,
    })
    //========重置弹框位置为水平垂直居中========================
    const autoCenter = () => {
        let left = (clientWidth - positonStyle.width) / 2
        let top = (clientHeight - positonStyle.height) / 2
        setPositionStyle({ ...positonStyle, left, top })
    };
    //============重置弹框宽高===============
    const autoReset = () => {
        let width = parseInt(props.width + "");
        let height = parseInt(props.height + "");
        setPositionStyle({ ...positonStyle, width, height })
    };
    //======重置弹框宽高及重新水平垂直居中======================
    const autoCenterAndReopen = () => {
        let left = (clientWidth - positonStyle.width) / 2;
        let top = (clientHeight - positonStyle.height) / 2;
        let width = parseInt(props.width + "");
        let height = parseInt(props.height + "");
        setPositionStyle({ ...positonStyle, width, height, top, left })
    }
    //================弹框初始化以及关闭的若干操作=======================
    React.useEffect(() => {
        // if (visible) {
            if (autoCenterWhenReOpen && !autoResetWhenReOpen) {
                autoCenter()
            } else if (!autoCenterWhenReOpen && autoResetWhenReOpen) {
                autoReset()
            } else if (autoCenterWhenReOpen && autoResetWhenReOpen) {
                autoCenterAndReopen()
            }
        // }
        return () => {
            isDrag = false
            isDragResize = false
            document.onmousemove = null;
        };

    }, [visible])

    //====================注册浏览器窗口改变后的事件=========================================
    React.useEffect(() => {
        window.addEventListener('resize', () => {
            clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
            clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
            isDrag = false;
            isDragResize = false;
            autoCenterWhenReOpen && autoCenter();
        });

    })


    // ============================= Style ==============================
    const contentStyle: React.CSSProperties = {};
    if (width !== undefined) {
        contentStyle.width = width;
    }
    if (height !== undefined) {
        contentStyle.height = height;
    }
    if (transformOrigin) {
        contentStyle.transformOrigin = transformOrigin;
    }

    function onPrepare() {
        const elementOffset = offset(dialogRef.current);

        setTransformOrigin(
            mousePosition
                ? `${mousePosition.x - elementOffset.left}px ${mousePosition.y - elementOffset.top}px`
                : '',
        );
    }

    // ============================= Render =============================
    let footerNode: React.ReactNode;
    if (footer) {
        footerNode = <div className={`${prefixCls}-footer`}>{footer}</div>;
    }

    let headerNode: React.ReactNode;
    if (title) {
        headerNode = (
            <div className={`${prefixCls}-header`}>
                <div className={`${prefixCls}-title`} id={ariaId}>
                    {title}
                </div>
            </div>
        );
    }

    let closer: React.ReactNode;
    if (closable) {
        closer = (
            <button type="button" onClick={onClose} aria-label="Close" className={`${prefixCls}-close`}>
                {closeIcon || <span className={`${prefixCls}-close-x`} />}
            </button>
        );
    }
    //==================定义外层loading================
    const Wrapper = ({ loadingProps, children }) =>
        loadingProps && Object.keys(loadingProps).length ? (
            <Spin {...loadingProps}>{children}</Spin>
        ) : (
            <React.Fragment>{children}</React.Fragment>
        );
    //========================拖拽===================
    const dragDown = (event) => {
        const e:any = event || window.event;
        dragStartPageX = e.pageX;
        dragStartPageY = e.pageY;
        leftOffset = positonStyle.left;
        topOffset = positonStyle.top;
        isDrag = true;
        document.onmousemove = null;
        document.onmousemove = (event) => {
            const e:any = event || window.event;
            const endPageX = e.pageX;
            const endPageY = e.pageY;
            if (isDrag) {
                const MAX_X = clientWidth - positonStyle.width;
                const MAX_Y = clientHeight - positonStyle.height;
                const moveX = Math.min(
                    Math.max(0, parseInt((leftOffset + endPageX - dragStartPageX) + "", 10)),
                    MAX_X,
                );
                const moveY = Math.min(
                    Math.max(0, parseInt((topOffset + endPageY - dragStartPageY) + "", 10)),
                    MAX_Y,
                );
                setPositionStyle({ ...positonStyle, left: moveX, top: moveY })

            }
        };
    };
    const dragUp = (e) => {
        isDrag = false;
        document.onmousemove = null;
    };
    //======================调整宽高==================
    const resizeDown = (event) => {
        const e = event || window.event;
        resizeStartClientX = e.clientX;
        resizeStartClientY = e.clientY;
        const modalWidth = positonStyle.width;
        const modalHeight = positonStyle.height;
        isDragResize = true;
        // document.onmousemove = null
        document.onmousemove = null;
        document.onmousemove = (event) => {
            const e:any = event || window.event;
            const endClientX = e.clientX;
            const endClientY = e.clientY;
            if (isDragResize) {
                // 设置偏移量,防止拖动到最右侧和最下方出现滚动条
                const offsetX = clientWidth > endClientX && clientWidth - endClientX < 10;
                const offsetY =
                    clientHeight < endClientY ||
                    (clientHeight > endClientY && clientHeight - endClientY < 13);
                let endWidth = (endClientX - resizeStartClientX) * MULTIPLE + modalWidth  < reszieMinWidth ? reszieMinWidth : (endClientX - resizeStartClientX) * MULTIPLE + modalWidth 
                let endHeight = (endClientY - resizeStartClientY) * MULTIPLE + modalHeight  < reszieMinHeight ? reszieMinHeight : (endClientY - resizeStartClientY) * MULTIPLE + modalHeight 
                setPositionStyle({
                    ...positonStyle, ...{
                        width: offsetX
                            ? positonStyle.width
                            : parseInt(endWidth, 10),
                        height: offsetY
                            ? positonStyle.height
                            : parseInt(endHeight, 10),
                    },
                })
                // const body = document.getElementById(id).querySelector('.ant-modal-body');
                const body = document.getElementById(id);
                props.onResize ? props.onResize({ width: body.offsetWidth, height: body.offsetHeight }) : null
            }
        };
    };

    const resizeUp = (e) => {
        isDragResize = false;
        document.onmousemove = null;
    };

    const content = (
        <Wrapper loadingProps={props.wholeLoadingProps}>
            <div className={`${prefixCls}-content`}>
                {closer}
                {headerNode}
                {dragable && (
                    <div
                        className="ant-modal-move-header"
                        onMouseDown={dragDown}
                        onMouseUp={dragUp}
                    />
                )}
                {resizable && (
                    <span
                        className="ant-modal-resize-flag-wrapper"
                        onMouseDown={resizeDown}
                        onMouseUp={resizeUp}
                    >
                        <RadiusBottomrightOutlined className="ant-modal-resize-flag" />
                    </span>
                )}
                <div className={`${prefixCls}-body`} style={bodyStyle} {...bodyProps}>
                    {children}
                </div>
                {footerNode}
            </div>
        </Wrapper>
    );

    return (
        <CSSMotion
            visible={visible}
            onVisibleChanged={onVisibleChanged}
            onAppearPrepare={onPrepare}
            onEnterPrepare={onPrepare}
            forceRender={forceRender}
            motionName={motionName}
            removeOnLeave={destroyOnClose}
            ref={dialogRef}
        >
            {({ className: motionClassName, style: motionStyle }, motionRef) => (
                <div
                    key="dialog-element"
                    role="document"
                    ref={motionRef}
                    id={id}
                    style={{ ...motionStyle, ...style, ...contentStyle, ...positonStyle, position: 'absolute' }}
                    className={classNames(prefixCls, className, motionClassName)}
                    onMouseDown={onMouseDown}
                    onMouseUp={onMouseUp}
                >
                    <div tabIndex={0} ref={sentinelStartRef} style={sentinelStyle} aria-hidden="true" />
                    <MemoChildren shouldUpdate={visible || forceRender}>
                        {modalRender ? modalRender(content) : content}
                    </MemoChildren>
                    <div tabIndex={0} ref={sentinelEndRef} style={sentinelStyle} aria-hidden="true" />
                </div>
            )}
        </CSSMotion>
    );
});

Content.displayName = 'Content';

export default Content;
