import { __rest } from "tslib";
import * as React from 'react';
import { useLocation } from 'react-router-dom';
import { runtime } from './adapter';
import { app as _app } from '../app/global-api';
import { widgetKeys } from './widgets';
import { get, set } from 'lodash-es';
import { createHistory } from './history';
export function useScrollTop() {
    const { pathname } = useLocation();
    React.useEffect(() => {
        runtime === null || runtime === void 0 ? void 0 : runtime.scrollTo(0, 0);
    }, [pathname]);
    return null;
}
function replaceStaticResourceAttribute(obj, replacer, paths, index = 0) {
    const path = paths[index];
    const value = get(obj, path);
    if (index === paths.length - 1) {
        try {
            if (value) {
                set(obj, path, replacer(value));
            }
        }
        catch (e) {
            console.error(e);
        }
    }
    else {
        if (Array.isArray(value)) {
            value.forEach((current) => {
                replaceStaticResourceAttribute(current, replacer, paths, index + 1);
            });
        }
        else {
            try {
                Object.values(value).forEach((current) => {
                    replaceStaticResourceAttribute(current, replacer, paths, index + 1);
                });
            }
            catch (e) { }
        }
    }
}
function processStaticResourceAttribute(data, replacer, property) {
    let segments = [property];
    if (/\.\*\.?/.test(property)) {
        segments = property === null || property === void 0 ? void 0 : property.trim().split('.').reduce((segments, path) => {
            const latest = segments.length ? segments.length - 1 : 0;
            const current = segments[latest];
            if (path === '*') {
                segments.push('');
            }
            else {
                segments[latest] = current ? `${current}.${path}` : path;
            }
            return segments;
        }, []);
    }
    try {
        replaceStaticResourceAttribute(data, replacer, segments);
    }
    catch (e) {
        console.error('处理静态资源失败:', e);
    }
}
const EMPTY_ARRAY = [];
/**
 * 用于处理自定义组件props传参结构，对系统变量进行保留
 * 曾用名：resolveComponentProps()
 */
export function useComponentProps(props, isPlainProps) {
    var _a;
    const emitRef = React.useRef(props.emit);
    const { __internal__ = {} } = _app || {};
    const { resolveStaticResourceUrl = (str) => str } = __internal__ || {};
    const reactBuiltinPorps = React.useMemo(() => ['ref', 'key', 'dangerouslySetInnerHTML', 'className', 'htmlFor', 'style', 'contentEditable', 'children'], []);
    const builtinProps = React.useMemo(() => [
        // react 保留字
        ...reactBuiltinPorps,
        // lowcode 保留字
        ...widgetKeys,
        'events',
        'classList',
        'widgetType',
        'staticResourceAttribute',
        // 小程序保留字
        'id',
        'class',
        'hidden',
        'slot',
    ], []);
    const { data = {}, staticResourceAttribute, emit, events, 
    /**
     * 排除复合组件所需独有属性
     */
    forIndexes: __, 
    /**
     * 排除 dom ref
     */
    domRef: ___, 
    /**
     * 排除 isInComposite
     * 如无必要 勿增实体
     */
    isInComposite: ____, children = EMPTY_ARRAY } = props, restProps = __rest(props, ["data", "staticResourceAttribute", "emit", "events", "forIndexes", "domRef", "isInComposite", "children"]);
    (_a = staticResourceAttribute === null || staticResourceAttribute === void 0 ? void 0 : staticResourceAttribute.forEach) === null || _a === void 0 ? void 0 : _a.call(staticResourceAttribute, (property) => {
        processStaticResourceAttribute(props.data, resolveStaticResourceUrl, property);
    });
    const customProps = Object.assign({}, data);
    // delete builtin props
    builtinProps.forEach((prop) => {
        delete customProps[prop];
    });
    emitRef.current = emit;
    /**
     * TODO: 可不依赖配置的事件列表，使用通用 proxy
     * 但存在问题：vue.CreateElement 中 on 可能遍历了 events 对象
     * proxy 会导致获取不到事件
     */
    const proxyEvents = React.useMemo(() => {
        return new Proxy(events.reduce((events, item) => {
            const propName = item;
            events[propName] = (e, options) => {
                /**
                 * emit 调用产生 promise
                 * 赋值给 dom 会产生 error: cannot convert object to primitive value
                 */
                emitRef.current(propName, e, options === null || options === void 0 ? void 0 : options.originEvent);
            };
            return events;
        }, {
            toJSON() {
                return {};
            },
        }), {
            get(obj, prop) {
                return prop in obj
                    ? obj[prop]
                    : (e, options) => {
                        /**
                         * emit 调用产生 promise
                         * 赋值给 dom 会产生 error: cannot convert object to primitive value
                         */
                        emitRef.current(prop, e, options === null || options === void 0 ? void 0 : options.originEvent);
                    };
            },
        });
    }, [emitRef, events]);
    if (!isPlainProps) {
        return Object.assign(Object.assign({}, props), { data: customProps, events: proxyEvents });
    }
    // 选区events处理
    const { _selectableBlockEvents = {} } = customProps, restData = __rest(customProps, ["_selectableBlockEvents"]);
    const { emit: _selectableBlockEmit } = _selectableBlockEvents;
    _selectableBlockEvents.events = new Proxy({}, {
        get(obj, prop) {
            return prop in obj ? obj[prop] : (e) => _selectableBlockEmit(prop, e);
        },
    });
    const result = Object.assign(Object.assign(Object.assign({}, restData), restProps), { children: Array.isArray(children) && !children.length ? EMPTY_ARRAY : children, _selectableBlockEvents, 
        /**
         * 覆盖原有的 events 事件名数组，采用通用代理
         */
        events: proxyEvents, emit });
    if (Array.isArray(result.children) && result.children.length === 0) {
        result.children = EMPTY_ARRAY;
    }
    return result;
}
export const OwnerComponentContext = React.createContext({ attached: false });
export function useHistoryMemo({ basename, isHash, type }) {
    const history = React.useMemo(() => {
        return createHistory({
            basename,
        }, isHash ? 'hash' : type);
    }, [basename, isHash]);
    return history;
}
