import { getInitializer } from '../helpers.js';
const normalize = (s) => s.replaceAll(/[\s\r\n]/g, '');
export class ArrayDriver {
    /** Add a single item to an array, skipping if duplicate. */
    static addArrayItem(sourceFile, item, array, finder) {
        const arrayExpr = ArrayDriver.resolveArray(sourceFile, array);
        if (!arrayExpr)
            return;
        if (!ArrayDriver.isDuplicate(arrayExpr, item, finder)) {
            arrayExpr.addElement(item, { useNewLines: true });
        }
    }
    /** Add multiple items to an array, skipping duplicates. */
    static addArrayItems(sourceFile, items, array) {
        const arrayExpr = ArrayDriver.resolveArray(sourceFile, array);
        if (!arrayExpr)
            return;
        const unique = ArrayDriver.getUniqueArrayItems(arrayExpr, items);
        if (unique.length > 0) {
            arrayExpr.addElements(unique, { useNewLines: true });
        }
    }
    /** Change the `useClass` of a provider object that matches `provide`. */
    static changeProviderArray(array, provide, adapter) {
        for (const value of array.getElements()) {
            if (value.getKindName() !== 'ObjectLiteralExpression')
                continue;
            const obj = value;
            const properties = obj.getProperties();
            let isTarget = false;
            for (const prop of properties) {
                if (prop.getName() === 'provide' &&
                    getInitializer(prop)?.getText() ===
                        provide) {
                    isTarget = true;
                }
                if (isTarget && prop.getName() === 'useClass') {
                    prop.setInitializer(adapter);
                    break;
                }
            }
        }
    }
    /** Remove an element from an array by its text. */
    static removeItem(array, item) {
        const el = array.getElements().find((e) => e.getText() === item);
        if (el)
            array.removeElement(el);
    }
    /** Remove a provider object from the array by its `provide` value. */
    static removeProviderArray(array, provide) {
        const elements = array.getElements();
        for (let i = elements.length - 1; i >= 0; i--) {
            const el = elements[i];
            if (el.getKindName() !== 'ObjectLiteralExpression')
                continue;
            const obj = el;
            const providesProp = obj.getProperty('provide');
            if (providesProp &&
                getInitializer(providesProp)?.getText() ===
                    provide) {
                array.removeElement(i);
            }
        }
    }
    static getUniqueArrayItems(array, items) {
        const existing = new Set(array.getElements().map((e) => normalize(e.getText())));
        return items.filter((item) => !existing.has(normalize(item)));
    }
    static isDuplicate(array, item, finder) {
        if (finder)
            return finder(item, array);
        const existing = array.getElements().map((e) => normalize(e.getText()));
        return existing.includes(normalize(item));
    }
    static resolveArray(sourceFile, array) {
        if (typeof array !== 'string')
            return array;
        const decl = sourceFile.getVariableDeclaration(array);
        return getInitializer(decl);
    }
}
