/**
 * @module SyncPeerInnerspace_V1
 */
import { delay, extractErrorMsg, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
import { GLOBAL_LOG_A_LOT } from '../../../core-constants.mjs';
import { SyncPeer_V1 } from '../sync-peer-v1.mjs';
import { putInSpace, registerNewIbGib } from '../../../witness/space/space-helper.mjs';
import { getSyncSagaFrameDependencyGraph, putInSpace_dnasThenNonDnas } from '../../sync-helpers.mjs';
import { toDto } from '../../../common/other/ibgib-helper.mjs';
const logalot = GLOBAL_LOG_A_LOT;
const logalotControlDomain = false;
const lcControlDomain = '[ControlDomain]';
/**
 * Concrete implementation of SyncPeer for local in-memory simulation (Innerspace to Innerspace).
 *
 * Acts as the "Network" layer, transferring data between two local spaces and
 * executing the receiver's coordinator logic.
 */
export class SyncPeerInnerspace_V1 extends SyncPeer_V1 {
    lc = `[${SyncPeerInnerspace_V1.name}]`;
    get classname() {
        return SyncPeerInnerspace_V1.name;
    }
    constructor(initialData, initialRel8ns) {
        super(initialData, initialRel8ns);
    }
    async ensureReceiverTempSpace() {
        const lc = `${this.lc}[${this.ensureReceiverTempSpace.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: bab87f15dea77cd4892bd8a8d2e65826)`);
            }
            if (!this.opts) {
                throw new Error(`(UNEXPECTED) this.opts falsy? (E: 0f85bd4c3efdbee2a829aca860c48926)`);
            }
            if (!this.opts.receiverTempSpace) {
                const { receiverMetaspace } = this.opts;
                const uuid = crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36);
                const tempSpaceName = `tmp_sync_recv_${uuid.substring(0, 8)}`;
                const receiverTempSpace = await receiverMetaspace.createNewLocalSpace({
                    opts: {
                        allowCancel: false,
                        spaceName: tempSpaceName,
                        getFnPrompt: receiverMetaspace.getFnPrompt,
                        logalot
                    }
                });
                if (!receiverTempSpace) {
                    throw new Error(`(UNEXPECTED) receiverTempSpace falsy? couldn't create a temp space? (E: a6b8f86b0f58384b884a33b82924b826)`);
                }
                await receiverTempSpace.initialized;
                this.opts.receiverTempSpace = receiverTempSpace;
            }
            return this.opts.receiverTempSpace;
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
    async sendContextRequest(context) {
        const lc = `${this.lc}[${this.sendContextRequest.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: bab87f15dea77cd4892bd8a8d2e65826)`);
            }
            if (!this.opts) {
                throw new Error(`(UNEXPECTED) this.opts falsy? (E: d8b1348e3233810128999596b1fa5826)`);
            }
            const { senderSpace, senderTempSpace, receiverSpace, receiverCoordinator, receiverMetaspace, receiverTempSpace } = this.opts;
            if (logalot) {
                console.log(`${lc} starting...Context: ${getIbGibAddr({ ibGib: context })}`);
            }
            const { sagaFrame } = context;
            // The context has already been validated, authenticated and authorized at this point.
            // #region sanity validation assertions
            if (!context.data) {
                throw new Error(`(UNEXPECTED) context.data falsy? (E: 1d2ac8a9b991d451e8900588057fe626)`);
            }
            if (!context.rel8ns) {
                throw new Error(`(UNEXPECTED) context.rel8ns falsy? (E: 3508786f0d8880bcadd346282a807826)`);
            }
            if (!context.rel8ns.sagaFrame) {
                throw new Error(`(UNEXPECTED) context.rel8ns.sagaFrame falsy? (E: ac06782ad538be406882605f0a83aa26)`);
            }
            if (!context.sagaFrame) {
                throw new Error(`(UNEXPECTED) context.sagaFrame falsy? (E: 79cd98a6d9b88a591f4596c8bc58ff26)`);
            }
            if (!sagaFrame.data) {
                throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: f30e290a8b770e1b387377420ea73a26)`);
            }
            if (!sagaFrame.rel8ns) {
                throw new Error(`(UNEXPECTED) sagaFrame.rel8ns falsy? (E: f888caa698b8cf6b4893b7fd6df09726)`);
            }
            if (!receiverTempSpace) {
                throw new Error(`(UNEXPECTED) receiverTempSpace falsy? (E: 3b46d838f6fc645c58b29215bfddb826)`);
            }
            if (!senderTempSpace) {
                throw new Error(`(UNEXPECTED) senderTempSpace falsy? (E: b187a8f913c2295ae90d7ae2b47b6a26)`);
            }
            // #endregion sanity validation assertions
            // let localSpace: IbGibSpaceAny;
            // let localTempSpace: IbGibSpaceAny;
            // let remoteSpace: IbGibSpaceAny;
            // let remoteTempSpace: IbGibSpaceAny;
            // if (getSyncSagaFrameOrigin({ sagaFrame: context.sagaFrame }) === SyncSagaFrameOrigin.sender) {
            //     localSpace = senderSpace;
            //     localTempSpace = senderTempSpace;
            //     remoteSpace = receiverSpace;
            //     remoteTempSpace = receiverTempSpace;
            // } else {
            //     localSpace = receiverSpace;
            //     localTempSpace = receiverTempSpace;
            //     remoteSpace = senderSpace;
            //     remoteTempSpace = senderSpace;
            // }
            const { sagaIbGib: _alreadyHave, msgStones, identities } = await getSyncSagaFrameDependencyGraph({
                sagaIbGib: sagaFrame,
                localSpace: senderSpace,
            });
            if (msgStones.length !== 1) {
                throw new Error(`(UNEXPECTED) msgStones.length !== 1? we're only geared for a single msg stone that is always present (not 0, not greater than 1) (E: 2d3138ed130f1aca116551889483e826)`);
            }
            const msg = msgStones[0];
            if (!msg.data) {
                throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`);
            }
            // send the context itself, then send the payload ibgibs separately.
            // in this innerspace, this just means putting the control ibgibs
            // first into the receiver durable space, then we will spin off a
            // promise to put any payload ibgibs in the receiver temp space.
            // We'll test a little latency also, to mimic a fuller, two-part
            // sync peer to ensure that other code is acting as expected.
            // we store inside out, meaning we do the dependencies first and
            // then the higher-level dependents.
            const payloadIbGibsControl = [
                ...identities, msg, sagaFrame, context
            ].map(x => toDto({ ibGib: x }));
            if (logalot) {
                console.log(`${lc} putting into receiverSpace: ${receiverSpace.ib} (I: 1ba18b14a26bdd0e7800da4812898826)`);
            }
            await putInSpace({
                ibGibs: payloadIbGibsControl,
                space: receiverSpace,
            });
            // register yet??
            for (const control of payloadIbGibsControl) {
                await registerNewIbGib({
                    ibGib: control,
                    space: receiverSpace,
                    fnBroadcast: undefined
                });
            }
            if (context.payloadIbGibsDomain && context.payloadIbGibsDomain.length > 0) {
                if (logalot) {
                    console.log(`${lc} putting into receiverTempSpace: ${receiverTempSpace.ib} (I: d0cea920b818393d68118bc8a1515526)`);
                }
                await putInSpace_dnasThenNonDnas({
                    ibGibs: context.payloadIbGibsDomain,
                    space: receiverTempSpace,
                });
                // no need to register right now, because we're putting into the
                // temp receiver space and we don't register until we commit
                // const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } =
                //     splitPerTjpAndOrDna({ ibGibs: payload_NonDnas });
            }
            // at this time, the receiver has received the control ibgibs AND
            // the payload ibgibs. so the receiver coordinator should be ready
            // to do its thing.
            const responseCtx = await receiverCoordinator.continueSync({
                sagaContext: context,
                metaspace: receiverMetaspace,
                mySpace: receiverSpace,
                myTempSpace: receiverTempSpace,
            });
            if (logalot) {
                console.log(`${lc} receiverCoordinator.continueSync responseCtx: ${responseCtx ? pretty(responseCtx) : 'undefined'} (I: fb2831decde1f2b3589021f85ab19126)`);
            }
            if (!responseCtx) {
                if (logalot) {
                    console.log(`${lc} receiver produced undefined response context. (I: 2e1888ffc9e836689d5b171887c36d26)`);
                }
                return undefined; /* <<<< returns early */
            }
            // at this point, we have received the full response from the
            // receiver coordinator. That coordinator has put the control ibgibs
            // in its durable space. Now we need to put the response's control
            // ibgibs in the sender's durable space (register them??), spin off
            // the process of any response payloads, and return the context.
            // get control ibgibs from the receiver space...
            const { msgStones: msgStonesResponse, identities: identitiesResponse } = await getSyncSagaFrameDependencyGraph({
                sagaIbGib: responseCtx.sagaFrame,
                localSpace: receiverSpace,
            });
            if (msgStonesResponse.length !== 1) {
                throw new Error(`(UNEXPECTED) msgStonesResponse.length !== 1? we're only geared for a single msg stone that is always present (not 0, not greater than 1) (E: 2d3138ed130f1aca116551889483e826)`);
            }
            const msgResponse = msgStonesResponse[0];
            if (!msgResponse.data) {
                throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`);
            }
            const responsePayloadIbGibsControl = [
                ...identities, msgResponse, responseCtx.sagaFrame, context
            ].map(x => toDto({ ibGib: x }));
            // ...put into sender's durable space
            await putInSpace({
                ibGibs: responsePayloadIbGibsControl,
                space: senderSpace,
            });
            // register yet??
            for (const control of responsePayloadIbGibsControl) {
                await registerNewIbGib({
                    ibGib: control,
                    space: senderSpace,
                    fnBroadcast: undefined
                });
            }
            // spin off the payloads, as that may take a long time
            const payloadIbGibsDomain_response = responseCtx.payloadIbGibsDomain;
            if (payloadIbGibsDomain_response) {
                new Promise(async (resolve, reject) => {
                    const lcPut = `${lc}[putPayloadsPromise]`;
                    try {
                        if (logalot) {
                            console.log(`${lcPut} starting... (I: 4133e736b4c80d2cf94448b87b206826)`);
                        }
                        // 2 seconds...i want to see huge blocks of logs entries for this to see this happening
                        const delayMs = 20;
                        for (let i = 0; i < 10; i++) {
                            console.warn(`${lc} ARTIFICIALLY DELAYING PAYLOADS TO MIMIC TRANSFER LATENCY. REMOVE THIS DELAY!! (W: 5e7b28f1daa82d955897e9d8cdb16f26)`);
                            await delay(delayMs);
                        }
                        await putInSpace_dnasThenNonDnas({
                            ibGibs: payloadIbGibsDomain_response,
                            space: senderTempSpace,
                        });
                        for (const payloadDomain of payloadIbGibsDomain_response) {
                            await this.payloadIbGibsDomainReceived$.next(payloadDomain);
                        }
                        if (logalot) {
                            console.log(`${lcPut} complete.`);
                        }
                        resolve();
                    }
                    catch (error) {
                        const errorMsg = `${lcPut} ${extractErrorMsg(error)}`;
                        console.error(errorMsg);
                        if (logalot) {
                            console.log(`${lcPut} complete. (errored)`);
                        }
                        reject(errorMsg);
                    }
                }); // spin off
                /**
                 * the caller should be getting these from the observable.
                 */
                delete responseCtx.payloadIbGibsDomain;
            }
            return responseCtx;
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
}
//# sourceMappingURL=sync-peer-innerspace-v1.mjs.map