import { MustardName } from '../typings';
import { consumption, getAppFromInstance, setReadDocumentName } from '../global';
import { handleDom, handleSelectors } from '../utils';

export function proxyDocument (appName:MustardName) {
    return new Proxy(document, {
        get: (target, key) => {
            if(key === 'defaultView') {
                return getAppFromInstance(appName)?.sandbox?.proxyWindow;
            }
            // 设置要消费的子应用标识
            if(target[key] instanceof Function) {
                return function (...args) {
                    setReadDocumentName(appName);
                    return target[key].call(target, ...args);
                };
            }
            return target[key];
        }
    });
}

export function changeDomPropety () {
    // 修改Document原型链
    const createElement = Document.prototype.createElement;
    const createElementNS = Document.prototype.createElementNS;
    const createTextNode = Document.prototype.createTextNode;
    const createComment = Document.prototype.createComment;
    const createDocumentFragment = Document.prototype.createDocumentFragment;
    const caretRangeFromPoint = Document.prototype.caretRangeFromPoint;
    
    Document.prototype.createElement = function (tagName:string, ...options) {
        return handleDom(createElement.call(this, tagName, ...options));
    };
    Document.prototype.createElementNS = function (...options) {
        return handleDom(createElementNS.call(this, ...options));
    };
    Document.prototype.createTextNode = function (...options) {
        return handleDom(createTextNode.call(this, ...options));
    };
    Document.prototype.createComment = function (...options) {
        return handleDom(createComment.call(this, ...options));
    };
    Document.prototype.createDocumentFragment = function (...options) {
        return handleDom(createDocumentFragment.call(this, ...options));
    };
    caretRangeFromPoint && (Document.prototype.caretRangeFromPoint = function (...options) {
        return handleDom(caretRangeFromPoint.call(this, ...options));
    });

    const getElementById = Document.prototype.getElementById;
    const querySelector = Document.prototype.querySelector;
    const querySelectorAll = Document.prototype.querySelectorAll;
    const getElementsByClassName = Document.prototype.getElementsByClassName;
    const getElementsByTagName = Document.prototype.getElementsByTagName;
    const getElementsByName = Document.prototype.getElementsByName;

    Document.prototype.getElementById = function (selectors:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const ele = miniRootDom?.querySelector(`#${selectors}`); 
            return handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
        }
        return getElementById.call(this, selectors);
    };
    Document.prototype.querySelector = function (selectors:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const ele = miniRootDom?.querySelector(handleSelectors(selectors));
            return handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
        }
        return querySelector.call(this, selectors);
    };
    Document.prototype.querySelectorAll = function (selectors:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const eles = miniRootDom?.querySelectorAll(handleSelectors(selectors));
            Array.from(eles).forEach((ele)=>{
                handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
            });
            return eles;
        }
        return querySelectorAll.call(this, selectors);
    };
    Document.prototype.getElementsByClassName = function (selectors:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const eles = miniRootDom?.getElementsByClassName(selectors);
            Array.from(eles).forEach((ele)=>{
                handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
            });
            return eles;
        }
        return getElementsByClassName.call(this, selectors);
    };
    Document.prototype.getElementsByTagName = function (selectors:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const eles = miniRootDom?.getElementsByTagName(handleSelectors(selectors));
            Array.from(eles).forEach((ele)=>{
                handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
            });
            return eles;
        }
        return getElementsByTagName.call(this, selectors);
    };
    Document.prototype.getElementsByName = function (name:string) {
        const appName = consumption();
        if(appName) {
            const miniRootDom = getAppFromInstance(appName)?.container;
            const eles = miniRootDom?.querySelectorAll(`[name=${name}]`);
            Array.from(eles).forEach((ele)=>{
                handleDom(ele, appName); // 已经消费过唯一标识，需要手动传递标识
            });
            return eles;
        }
        return getElementsByName.call(this, name);
    };
}