/*
 * Copyright 2025 The Lynx Authors. All rights reserved.
 * Licensed under the Apache License Version 2.0 that can be found in the
 * LICENSE file in the root directory of this source tree.
 */
import { MainThreadServerContext, StyleSheetResource } from '../wasm.js';
import { LYNX_TAG_TO_HTML_TAG_MAP, uniqueIdSymbol, lynxDefaultDisplayLinearAttribute, lynxEntryNameAttribute, } from '../../constants.js';
import { __AddConfig, __AddDataset, __AddEvent, __ElementIsEqual, __FirstElement, __GetChildren, __GetComponentID, __GetConfig, __GetDataByKey, __GetDataset, __GetElementConfig, __GetElementUniqueID, __GetEvent, __GetEvents, __GetPageElement, __GetParent, __GetTemplateParts, __InsertElementBefore, __LastElement, __MarkPartElement, __MarkTemplateElement, __NextElement, __RemoveElement, __ReplaceElement, __ReplaceElements, __SetConfig, __SetDataset, __SetEvents, __SwapElement, __UpdateComponentID, __UpdateComponentInfo, __UpdateListCallbacks, getUniqueId, } from './pureElementAPIs.js';
export function createElementAPI(mtsBinding, styleInfo, viewAttributes, config) {
    const wasmContext = new MainThreadServerContext(viewAttributes, config.enableCSSSelector, config.transformVW, config.transformVH, config.transformREM);
    if (styleInfo) {
        const resource = new StyleSheetResource(styleInfo, undefined);
        wasmContext.push_style_sheet(resource);
    }
    let pageElementId;
    function getAttribute(element, key) {
        return wasmContext.get_attribute(element[uniqueIdSymbol], key) || undefined;
    }
    const __SetCSSId = (elements, cssId, entryName) => {
        const uniqueIds = elements.map((element) => element[uniqueIdSymbol]);
        wasmContext.set_css_id(new Uint32Array(uniqueIds), cssId ?? 0, entryName);
    };
    const __SetClasses = (element, classname) => {
        const el = element;
        if (classname) {
            wasmContext.set_attribute(el[uniqueIdSymbol], 'class', classname);
        }
        else {
            wasmContext.remove_attribute(el[uniqueIdSymbol], 'class');
        }
    };
    const __AddClass = (element, className) => {
        const el = element;
        wasmContext.add_class(el[uniqueIdSymbol], className);
    };
    return {
        globalThisAPIs: {
            // Pure/Throwing Methods
            __GetID: ((element) => {
                return getAttribute(element, 'id') ?? null;
            }),
            __GetTag: ((element) => {
                const el = element;
                const tag = wasmContext.get_tag(el[uniqueIdSymbol]) ?? '';
                // Reverse-map HTML tag to Lynx tag (consistent with CSR `__GetTag` behavior)
                for (const [lynxTag, htmlTag] of Object.entries(LYNX_TAG_TO_HTML_TAG_MAP)) {
                    if (tag === htmlTag) {
                        return lynxTag;
                    }
                }
                return tag;
            }),
            __GetAttributes: ((element) => {
                const el = element;
                return wasmContext.get_attributes(el[uniqueIdSymbol]);
            }),
            __GetAttributeByName: (element, name) => {
                return getAttribute(element, name) ?? null;
            },
            __GetClasses: ((element) => {
                const cls = getAttribute(element, 'class');
                if (!cls)
                    return [];
                return cls.split(/\s+/).filter((c) => c.length > 0);
            }),
            __GetParent: ((element) => {
                const id = getUniqueId(element);
                const parentId = wasmContext.get_parent(id);
                if (parentId !== undefined) {
                    return { [uniqueIdSymbol]: parentId };
                }
                return null;
            }),
            __GetChildren,
            __AddEvent,
            __GetEvent,
            __GetEvents,
            __SetEvents,
            __UpdateListCallbacks,
            __GetConfig,
            __SetConfig,
            __GetElementConfig,
            __GetComponentID,
            __GetDataset,
            __SetDataset,
            __AddDataset,
            __GetDataByKey,
            __ElementIsEqual,
            __GetElementUniqueID,
            __FirstElement,
            __LastElement,
            __NextElement,
            __RemoveElement: ((parent, child) => {
                const parentId = getUniqueId(parent);
                const childId = getUniqueId(child);
                wasmContext.remove_child(parentId, childId);
            }),
            __ReplaceElement: ((newElement, oldElement) => {
                const newId = getUniqueId(newElement);
                const oldId = getUniqueId(oldElement);
                wasmContext.replace_element(newId, oldId);
            }),
            __SwapElement,
            __SetCSSId,
            __SetClasses: config.enableCSSSelector
                ? __SetClasses
                : ((element, classname) => {
                    __SetClasses(element, classname);
                    const el = element;
                    wasmContext.update_css_og_style(el[uniqueIdSymbol], getAttribute(el, lynxEntryNameAttribute));
                }),
            __AddClass,
            __AddConfig,
            __UpdateComponentInfo,
            __UpdateComponentID,
            __MarkTemplateElement,
            __MarkPartElement,
            __GetTemplateParts,
            __GetPageElement,
            __InsertElementBefore: ((parent, child, ref) => {
                const parentId = getUniqueId(parent);
                const childId = getUniqueId(child);
                const refId = ref ? getUniqueId(ref) : undefined;
                wasmContext.insert_before(parentId, childId, refId);
            }),
            __ReplaceElements: ((parent, newChildren, oldChildren) => {
                const parentId = getUniqueId(parent);
                const newArr = Array.isArray(newChildren) ? newChildren : [newChildren];
                const newIds = new Uint32Array(newArr.map(getUniqueId));
                const oldArr = oldChildren
                    ? (Array.isArray(oldChildren) ? oldChildren : [oldChildren])
                    : [];
                const oldIds = new Uint32Array(oldArr.map(getUniqueId));
                wasmContext.replace_elements(parentId, newIds, oldIds);
            }),
            // Context-Dependent Methods
            __CreateView: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('x-view', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateText: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('x-text', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateImage: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('x-image', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateRawText: ((text) => {
                const id = wasmContext.create_element('raw-text');
                wasmContext.set_attribute(id, 'text', text);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateScrollView: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('scroll-view', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateElement: ((tagName, parentComponentUniqueId) => {
                const htmlTag = LYNX_TAG_TO_HTML_TAG_MAP[tagName] ?? tagName;
                const id = wasmContext.create_element(htmlTag, parentComponentUniqueId);
                const el = { [uniqueIdSymbol]: id };
                if (!config.enableCSSSelector) {
                    wasmContext.set_attribute(id, 'l-uid', id.toString());
                }
                return el;
            }),
            __CreateComponent: ((parentComponentUniqueId, _componentID, _cssID, entryName, name) => {
                const id = wasmContext.create_element('x-view', parentComponentUniqueId, _cssID, _componentID); // Component host
                const el = { [uniqueIdSymbol]: id };
                if (!config.enableCSSSelector) {
                    wasmContext.set_attribute(id, 'l-uid', id.toString());
                }
                if (entryName) {
                    wasmContext.set_attribute(id, 'lynx-entry-name', entryName);
                }
                if (name) {
                    wasmContext.set_attribute(id, 'name', name);
                }
                return el;
            }),
            __CreateWrapperElement: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('lynx-wrapper', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreateList: ((parentComponentUniqueId) => {
                const id = wasmContext.create_element('x-list', parentComponentUniqueId);
                return { [uniqueIdSymbol]: id };
            }),
            __CreatePage: ((_componentID, _cssID) => {
                const id = wasmContext.create_element('div', 0, _cssID, _componentID);
                pageElementId = id;
                const el = { [uniqueIdSymbol]: id };
                if (!config.enableCSSSelector) {
                    wasmContext.set_attribute(id, 'l-uid', id.toString());
                }
                wasmContext.set_attribute(id, 'part', 'page');
                if (config.defaultDisplayLinear === false) {
                    wasmContext.set_attribute(id, lynxDefaultDisplayLinearAttribute, 'false');
                }
                if (config.defaultOverflowVisible === true) {
                    wasmContext.set_attribute(id, 'lynx-default-overflow-visible', 'true');
                }
                return el;
            }),
            __AppendElement: ((parent, child) => {
                const parentId = getUniqueId(parent);
                const childId = getUniqueId(child);
                wasmContext.append_child(parentId, childId);
            }),
            __SetAttribute: ((element, name, value) => {
                const el = element;
                let valStr = '';
                if (value == null) {
                    valStr = '';
                }
                else {
                    valStr = value.toString();
                }
                wasmContext.set_attribute(el[uniqueIdSymbol], name, valStr);
            }),
            __SetInlineStyles: ((element, value) => {
                const uniqueId = element[uniqueIdSymbol];
                if (!value) {
                    wasmContext.remove_attribute(uniqueId, 'style');
                }
                else {
                    if (typeof value === 'string') {
                        if (!wasmContext.set_inline_styles_in_str(uniqueId, value)) {
                            wasmContext.set_attribute(uniqueId, 'style', value);
                        }
                    }
                    else if (!value) {
                        wasmContext.remove_attribute(uniqueId, 'style');
                    }
                    else {
                        const vec = [];
                        for (const [k, v] of Object.entries(value)) {
                            if (v != null) {
                                vec.push(k, v.toString());
                            }
                        }
                        wasmContext.set_inline_styles_in_key_value_vec(uniqueId, vec);
                    }
                }
            }),
            __AddInlineStyle: ((element, key, value) => {
                const uniqueId = element[uniqueIdSymbol];
                let valStr = null;
                if (value != null) {
                    valStr = value.toString();
                }
                if (typeof key === 'number') {
                    return wasmContext.set_inline_styles_number_key(uniqueId, key, valStr);
                }
                else {
                    return wasmContext.add_inline_style_raw_string_key(uniqueId, key.toString(), valStr);
                }
            }),
            __ElementAnimate: () => { },
            __FlushElementTree: (() => {
                if (pageElementId !== undefined) {
                    mtsBinding.ssrResult = wasmContext.generate_html(pageElementId);
                }
            }),
            __SetID: ((element, id) => {
                wasmContext.set_attribute(element[uniqueIdSymbol], 'id', id ?? '');
            }),
            __InvokeUIMethod: () => {
                throw new Error('Not yet Implemented');
            },
            __QuerySelector: () => {
                throw new Error('Not yet Implemented');
            },
            __QuerySelectorAll: () => {
                throw new Error('Not yet Implemented');
            },
        },
        wasmContext,
    };
}
//# sourceMappingURL=createElementAPI.js.map