import { Arr, Optional } from '@ephox/katamari';
import { Compare, Insert } from '@ephox/sugar';
import * as Attachment from '../../api/system/Attachment';
import * as Patching from '../../dom/Patching';
import * as InternalAttachment from '../../system/InternalAttachment';
import { withoutReuse, withReuse } from './ReplacingAll';
const virtualReplace = (component, replacee, replaceeIndex, childSpec) => {
    InternalAttachment.virtualDetach(replacee);
    const child = Patching.patchSpecChild(component.element, replaceeIndex, childSpec, component.getSystem().buildOrPatch);
    InternalAttachment.virtualAttach(component, child);
    component.syncComponents();
};
const insert = (component, insertion, childSpec) => {
    const child = component.getSystem().build(childSpec);
    Attachment.attachWith(component, child, insertion);
};
const replace = (component, replacee, replaceeIndex, childSpec) => {
    Attachment.detach(replacee);
    insert(component, (p, c) => Insert.appendAt(p, c, replaceeIndex), childSpec);
};
const set = (component, replaceConfig, replaceState, data) => {
    const replacer = replaceConfig.reuseDom ? withReuse : withoutReuse;
    return replacer(component, data);
};
const append = (component, replaceConfig, replaceState, appendee) => {
    insert(component, Insert.append, appendee);
};
const prepend = (component, replaceConfig, replaceState, prependee) => {
    insert(component, Insert.prepend, prependee);
};
// NOTE: Removee is going to be a component, not a spec.
const remove = (component, replaceConfig, replaceState, removee) => {
    const children = contents(component, replaceConfig);
    const foundChild = Arr.find(children, (child) => Compare.eq(removee.element, child.element));
    foundChild.each(Attachment.detach);
};
// TODO: Rename
const contents = (component, _replaceConfig) => component.components();
const replaceAt = (component, replaceConfig, replaceState, replaceeIndex, replacer) => {
    const children = contents(component, replaceConfig);
    return Optional.from(children[replaceeIndex]).map((replacee) => {
        replacer.fold(() => Attachment.detach(replacee), (r) => {
            const replacer = replaceConfig.reuseDom ? virtualReplace : replace;
            replacer(component, replacee, replaceeIndex, r);
        });
        return replacee;
    });
};
const replaceBy = (component, replaceConfig, replaceState, replaceePred, replacer) => {
    const children = contents(component, replaceConfig);
    return Arr.findIndex(children, replaceePred).bind((replaceeIndex) => replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer));
};
export { append, prepend, remove, replaceAt, replaceBy, set, contents };
//# sourceMappingURL=ReplaceApis.js.map