// 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 { profileEnd, profileStart } from './debug/utils.js';
import { hydrate } from './hydrate.js';
import { componentAtIndexFactory, enqueueComponentFactory } from './list.js';
export class ListUpdateInfoRecording {
    list;
    constructor(list) {
        this.list = list;
        this.oldChildNodes = list.childNodes;
        // this.oldChildNodesSet = new Set(this.oldChildNodes);
    }
    // private __commitAndReset() {
    //   (this.__pendingAttributes ??= []).push(this.__toAttribute());
    //   this.oldChildNodes = this.list.childNodes;
    //   this.oldChildNodesSet = new Set(this.oldChildNodes);
    //   this.removeChild1.clear();
    //   this.removeChild2.clear();
    //   this.insertBefore.clear();
    //   this.appendChild.length = 0;
    //   this.platformInfoUpdate.clear();
    // }
    flush() {
        if (!this.list.__elements) {
            return undefined;
        }
        const elementIndex = this.list.__snapshot_def.slot[0][1];
        const listElement = this.list.__elements[elementIndex];
        // this.__pendingAttributes?.forEach(pendingAttribute => {
        //   __SetAttribute(listElement, "update-list-info", pendingAttribute);
        //   __FlushElementTree(listElement);
        // });
        const updateListInfo = this.__toAttribute();
        if (__PROFILE__) {
            const listID = __GetElementUniqueID(listElement);
            profileStart(`ReactLynx::listFlush::updateListInfo`, {
                args: {
                    'list id': String(listID),
                    'update list info': JSON.stringify(updateListInfo),
                },
            });
        }
        __SetAttribute(listElement, 'update-list-info', updateListInfo);
        const [componentAtIndex, componentAtIndexes] = componentAtIndexFactory(this.list.childNodes, hydrate);
        __UpdateListCallbacks(listElement, componentAtIndex, enqueueComponentFactory(), componentAtIndexes);
        if (__PROFILE__) {
            profileEnd();
        }
        return this.list.__id;
    }
    getAttachedListId() {
        if (!this.list.__elements) {
            return undefined;
        }
        return this.list.__id;
    }
    oldChildNodes;
    // private oldChildNodesSet: Set<SnapshotInstance>;
    removeChild = new Set();
    insertBefore = new Map(); // insert V before K
    appendChild = [];
    platformInfoUpdate = new Map();
    onInsertBefore(newNode, existingNode) {
        if (newNode.parentNode) {
            // if (!this.oldChildNodesSet.has(newNode)) {
            //   this.__commitAndReset();
            // }
            this.removeChild.add(newNode);
        }
        if (existingNode) {
            // if (!this.oldChildNodesSet.has(existingNode)) {
            //   this.__commitAndReset();
            // }
            const newChildren = this.insertBefore.get(existingNode) ?? [];
            newChildren.push(newNode);
            this.insertBefore.set(existingNode, newChildren);
        }
        else {
            this.appendChild.push(newNode);
        }
    }
    onRemoveChild(child) {
        // if (!this.oldChildNodesSet.has(child)) {
        //   this.__commitAndReset();
        // }
        this.removeChild.add(child);
    }
    onSetAttribute(child, attr, _oldAttr) {
        this.platformInfoUpdate.set(child, attr);
    }
    __toAttribute() {
        const { removeChild, insertBefore, appendChild, platformInfoUpdate } = this;
        const removals = [];
        const insertions = [];
        const updates = [];
        let j = 0;
        for (let i = 0; i < this.oldChildNodes.length; i++, j++) {
            const child = this.oldChildNodes[i];
            if (platformInfoUpdate.has(child)) {
                updates.push({
                    ...platformInfoUpdate.get(child),
                    from: +j,
                    to: +j,
                    // no flush
                    flush: false,
                    type: child.type,
                });
            }
            if (insertBefore.has(child)) {
                const children = insertBefore.get(child);
                children.forEach(c => {
                    insertions.push({
                        position: j,
                        type: c.type,
                        ...c.__listItemPlatformInfo,
                    });
                    j++;
                });
            }
            if (removeChild.has(child)) {
                removals.push(i);
                removeChild.delete(child);
                j--;
            }
        }
        for (let i = 0; i < appendChild.length; i++) {
            const child = appendChild[i];
            insertions.push({
                position: j + i,
                type: child.type,
                ...child.__listItemPlatformInfo,
            });
        }
        insertions.sort((a, b) => a.position - b.position);
        removals.sort((a, b) => a - b);
        if (SystemInfo.lynxSdkVersion === '2.14'
            || SystemInfo.lynxSdkVersion === '2.15'
            || SystemInfo.lynxSdkVersion === '2.16'
            || SystemInfo.lynxSdkVersion === '2.17'
            || SystemInfo.lynxSdkVersion === '2.18') {
            const elementIndex = this.list.__snapshot_def.slot[0][1];
            const listElement = this.list.__elements[elementIndex];
            // `__GetAttributeByName` is available since Lynx 2.14
            if (__GetAttributeByName(listElement, 'custom-list-name') === 'list-container') {
                // `updateAction` must be full (not incremental) when Lynx version <= 2.18 and
                // when `custom-list-name` is `list-container` (available when Lynx version >= 2.14) is true,
                updates.length = 0;
                this.list.childNodes.forEach((child, index) => {
                    updates.push({
                        ...child.__listItemPlatformInfo,
                        from: index,
                        to: index,
                        // no flush
                        flush: false,
                        type: child.type,
                    });
                });
            }
        }
        return {
            insertAction: insertions,
            removeAction: removals,
            updateAction: updates,
        };
    }
    toJSON() {
        // if (this.__pendingAttributes) {
        //   return [...this.__pendingAttributes, this.__toAttribute()];
        // } else {
        //   return [this.__toAttribute()];
        // }
        return [this.__toAttribute()];
    }
}
//# sourceMappingURL=listUpdateInfo.js.map