/**
 * @module SyncPeerInnerspace_V1
 */
import { extractErrorMsg } 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 { getFromSpace, putInSpace } from '../../../witness/space/space-helper.mjs';
import { newupSubject } from '../../../common/pubsub/subject/subject-helper.mjs';
const logalot = GLOBAL_LOG_A_LOT || true;
const logalotControlDomain = true;
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}]`;
    payloadIbGibsDomainReceived$;
    senderSpace;
    senderTempSpace;
    receiverCoordinator;
    receiverMetaspace;
    receiverSpace;
    receiverTempSpace;
    get classname() {
        return SyncPeerInnerspace_V1.name;
    }
    constructor(opts, initialData, initialRel8ns) {
        super(initialData, initialRel8ns);
        const { senderSpace, senderTempSpace, receiverCoordinator, receiverMetaspace, receiverSpace, receiverTempSpace } = opts;
        this.senderSpace = senderSpace;
        this.senderTempSpace = senderTempSpace;
        this.receiverCoordinator = receiverCoordinator;
        this.receiverMetaspace = receiverMetaspace;
        this.receiverSpace = receiverSpace;
        this.receiverTempSpace = receiverTempSpace;
    }
    async initialize() {
        this.payloadIbGibsDomainReceived$ = await newupSubject();
    }
    async ensureReceiverTempSpace() {
        if (!this.receiverTempSpace) {
            const { receiverMetaspace } = this;
            const uuid = crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36);
            const tempSpaceName = `tmp_sync_recv_${uuid.substring(0, 8)}`;
            const receiverTempSpace = await this.receiverMetaspace.createNewLocalSpace({
                opts: {
                    allowCancel: false,
                    spaceName: tempSpaceName,
                    getFnPrompt: this.receiverMetaspace.getFnPrompt,
                    logalot
                }
            });
            if (!receiverTempSpace) {
                throw new Error(`(UNEXPECTED) receiverTempSpace falsy? couldn't create a temp space? (E: a6b8f86b0f58384b884a33b82924b826)`);
            }
            await receiverTempSpace.initialized;
            this.receiverTempSpace = receiverTempSpace;
        }
        return this.receiverTempSpace;
    }
    async getLocalIbGib(addr) {
        const lc = `${this.lc}[${this.getLocalIbGib.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: 27b248cb9801eeb2386b71485389a826)`);
            }
            console.warn(`${lc} possibly a bottleneck here, getLocalIbGib only gets a single ibgib... (W: 2fd448a435480e6b128f6b8bcbef4826)`);
            const resGet = await getFromSpace({ space: this.senderSpace, addr });
            if (resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1) {
                const ibGib = resGet.ibGibs[0];
                return ibGib;
            }
            else {
                throw new Error(`couldn't get addr (${addr}) from local space ${this.senderSpace}. reason: ${resGet.errorMsg ?? 'unknown error (E: 926ef8bf4fcc299ab89dba34ea691a26)'} (E: d8a89807e471d3f8b938ab21df44cb26)`);
            }
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
    async push(addrs) {
        const lc = `${this.lc}[${this.push.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: 07bce80be18f3259b8a311ed9c4da926)`);
            }
            // silly defensive checks because this has been a ridiculous development cycle
            if (!this.senderSpace) {
                throw new Error(`(UNEXPECTED) this.senderSpace falsy? (E: 503e288168f5d297f4d4e028bc538826)`);
            }
            if (!this.receiverSpace) {
                throw new Error(`(UNEXPECTED) this.receiverSpace falsy? (E: 0bd7c1a0ba4868ac7a260e15b504e826)`);
            }
            await this.transfer({ addrs, from: this.senderSpace, to: this.receiverSpace });
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
    async pull(addrs) {
        const lc = `${this.lc}[${this.pull.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: b16a28ed0dc8f52f1838ee257d9b1126)`);
            }
            // silly defensive checks because this has been a ridiculous development cycle
            if (!this.receiverSpace) {
                throw new Error(`(UNEXPECTED) this.receiverSpace falsy? (E: bd2fdfa89ba4c89a185b68e9bb1f1c26)`);
            }
            if (!this.senderTempSpace) {
                throw new Error(`(UNEXPECTED) this.senderTempSpace falsy? (E: b23fa55713f881493dac4a9835ac7326)`);
            }
            await this.transfer({ addrs, from: this.receiverSpace, to: this.senderTempSpace });
        }
        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}]`;
        const { receiverSpace, receiverCoordinator, receiverMetaspace } = this;
        try {
            if (logalot) {
                console.log(`${lc} starting...Context: ${getIbGibAddr({ ibGib: context })}`);
            }
            // 0. Validate context (naive, not business logic validation)
            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)`);
            }
            // validate the context, sagaFrame, and identity(s)
            // persist the context, sagaframe, identity(s) ONLY in the receiver's durable space
            // if sending domain ibgibs...
            //   verify the domain ibgibs intrinsically. 
            //   persist the domain ibgibs in the receiver's temp space (push all addrs?)
            //   await until all domain ibgibs are in receiver's temp space
            // process the context with the receiver's coordinator to get a new response context
            // analyze the response context
            //   validate context intrinsically
            //   validate return identity if present
            // persist the response context's dependency graph (context, saga frame and msg(s), identities)
            // if response has payload domain ibgibs, 
            //   spin off...
            //     pull domain ibgibs to local temp space
            //     publish domain ibgibs to observable
            //     when all domain ibgibs are pulled, publish complete to the observable
            // return resulting context ibgib (which the caller should get BEFORE the domain ibgibs observable completes)
            throw new Error(`not implemented (E: 72840872e252d9f7380f1998b5a0c826)`);
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
    }
    /**
     * Helper to copy single ibgib from A to B.
     */
    async transfer({ addrs, from, to }) {
        const lc = `${this.lc}[${this.transfer.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: f1145dc75a461afc885efe984f08d426)`);
            }
            console.error(`${lc} NAG ERROR (DOES NOT THROW): This needs to be adapted to be able to pull from multiple spaces. IOW, the 'from' param should be an array of spaces. This is because we need to be checking both durable and temp spaces when querying. (E: 823f3856b8b82ece080868e85ded0826)`);
            // 1. Get from Source
            const resGet = await getFromSpace({ space: from, addrs });
            if (!resGet.success || !resGet.ibGibs || resGet.ibGibs.length !== addrs.length) {
                if (!resGet.rawResultIbGib) {
                    throw new Error(`(UNEXPECTED) resGet.rawResultIbGib falsy? (E: b829f827a378890bcf7dc3d41c908826)`);
                }
                if (!resGet.rawResultIbGib.data) {
                    throw new Error(`(UNEXPECTED) resGet.rawResultIbGib.data falsy? (E: 8d15341d8fa8fc96297425e3c6e39226)`);
                }
                const data = resGet.rawResultIbGib.data;
                throw new Error(`${lc} Failed to get all ${addrs} from source space ${from.ib}. resGet.errorMsg: ${resGet.errorMsg}. failed info: ${JSON.stringify(data)} (E: 4ed3383573382920c80054d7c1024626)`);
            }
            const ibGibs = resGet.ibGibs.concat();
            // 2. Put in Dest
            // Note: putInSpace handles existence check usually, or we can check.
            const resPut = await putInSpace({ space: to, ibGibs });
            if (resPut.success) {
                console.error(`${lc} NAG ERROR: (SORT OF AN ERROR, DID NOT THROW): is the sync peer responsible for calling registerNewIbGib?? I'm not sure at this point if that is true, rather, I think that it probably is NOT responsible for this. But I'm putting this error msg as a nag message until this is resolved. (E: 00086833e294ee834800046801c47826) `);
            }
            else {
                throw new Error(`ERROR: successfully got addrs (${addrs}) from space (${from.ib}), BUT failed to put into space (${to.ib}). resPut.errorMsg: ${resPut.errorMsg}. timedOut: ${resPut.timedOut}. (E: c1044e14cc1db72d28a2240819dab826)`);
            }
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
}
//# sourceMappingURL=sync-peer-innerspace-v1.mjs.map