var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { KeyShareType } from '@getpara/user-management-client';
import { NativeModules } from 'react-native';
import { AsyncStorage } from '../AsyncStorage.js';
import { KeychainStorage } from '../KeychainStorage.js';
const { ParaSignerModule } = NativeModules;
function keygenRequest(ctx, userId, walletId, protocolId) {
    return __awaiter(this, void 0, void 0, function* () {
        const { data } = yield ctx.mpcComputationClient.post('/wallets', {
            userId,
            walletId,
            protocolId,
        });
        return data;
    });
}
function signMessageRequest(ctx, userId, walletId, protocolId, message, signer) {
    return __awaiter(this, void 0, void 0, function* () {
        const { data } = yield ctx.mpcComputationClient.post(`/wallets/${walletId}/messages/sign`, {
            userId,
            protocolId,
            message,
            signer,
        });
        return data;
    });
}
function sendTransactionRequest(ctx, userId, walletId, protocolId, transaction, signer, chainId) {
    return __awaiter(this, void 0, void 0, function* () {
        const { data } = yield ctx.mpcComputationClient.post(`/wallets/${walletId}/transactions/send`, {
            userId,
            protocolId,
            transaction,
            signer,
            chainId,
        });
        return data;
    });
}
export class ReactNativeUtils {
    constructor() {
        this.sdkType = 'REACT_NATIVE';
        this.localStorage = new AsyncStorage();
        this.sessionStorage = new AsyncStorage();
        this.secureStorage = new KeychainStorage();
        this.isSyncStorage = false;
        this.eventHandlers = new Map();
    }
    addEventListener({ event, handler }) {
        if (!this.eventHandlers.has(event)) {
            this.eventHandlers.set(event, new Set());
        }
        this.eventHandlers.get(event).add(handler);
    }
    removeEventListener({ event, handler }) {
        const handlers = this.eventHandlers.get(event);
        if (handlers) {
            handlers.delete(handler);
            if (handlers.size === 0) {
                this.eventHandlers.delete(event);
            }
        }
    }
    postMessage({ data }) {
        var _a, _b;
        if (data && typeof data === 'object' && 'type' in data) {
            const event = data.type;
            (_a = this.eventHandlers.get(event)) === null || _a === void 0 ? void 0 : _a.forEach(h => h(data));
            // Also notify 'message' catch-all handlers
            if (event !== 'message') {
                (_b = this.eventHandlers.get('message')) === null || _b === void 0 ? void 0 : _b.forEach(h => h(data));
            }
        }
    }
    emitEvent({ event, data }) {
        const eventData = {
            type: event,
            payload: data,
        };
        this.postMessage({ data: eventData });
    }
    // only used in web for now, can implement functionality if ever needed for mobile
    generateBlumPrimes(_ctx) {
        return __awaiter(this, void 0, void 0, function* () {
            throw new Error('method not implemented');
        });
    }
    keygen(ctx, userId, type, _secretKey, _sessionCookie, _emailProps) {
        return __awaiter(this, void 0, void 0, function* () {
            const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
                type,
                useTwoSigners: true,
                scheme: ctx.useDKLS ? 'DKLS' : 'CGGMP',
            });
            if (ctx.mpcComputationClient && !ctx.useDKLS) {
                const { signer } = yield keygenRequest(ctx, userId, walletId, protocolId);
                return { signer, walletId };
            }
            const createAccountFn = !ctx.useDKLS ? ParaSignerModule.createAccount : ParaSignerModule.dklsCreateAccount;
            const signer = yield createAccountFn(walletId, protocolId, KeyShareType.USER, userId);
            return { signer, walletId };
        });
    }
    refresh(_ctx, _sessionCookie, _userId, _walletId, _share, _oldPartnerId, _newPartnerId) {
        throw new Error('Method not implemented.');
    }
    preKeygen(_ctx, _partnerId, _email, _secretKey, _sessionCookie) {
        throw new Error('Method not implemented.');
    }
    getPrivateKey(_ctx, _userId, _walletId, _share, _sessionCookie) {
        throw new Error('Method not implemented.');
    }
    openPopup(popupUrl) {
        if (this.transactionReviewHandler) {
            this.transactionReviewHandler(popupUrl);
            return;
        }
        throw new Error('openPopup is not supported on React Native. Use setTransactionReviewHandler() to handle transaction review URLs.');
    }
    baseSignTransaction(ctx, userId, walletId, protocolId, share, rlpEncodedTxBase64, chainId, isDKLS) {
        return __awaiter(this, void 0, void 0, function* () {
            if (ctx.mpcComputationClient && !isDKLS) {
                const signature = (yield sendTransactionRequest(ctx, userId, walletId, protocolId, rlpEncodedTxBase64, share, chainId))
                    .signature;
                return { signature };
            }
            const sendTransactionFn = isDKLS ? ParaSignerModule.dklsSendTransaction : ParaSignerModule.sendTransaction;
            const signature = yield sendTransactionFn(protocolId, share, rlpEncodedTxBase64, userId);
            return { signature: signature.slice(2) };
        });
    }
    sendTransaction(ctx, userId, walletId, share, rlpEncodedTxBase64, chainId, _sessionCookie, isDKLS) {
        return __awaiter(this, void 0, void 0, function* () {
            const { data } = yield ctx.client.sendTransaction(userId, walletId, {
                transaction: rlpEncodedTxBase64,
                chainId,
            });
            if (data.pendingTransactionId) {
                return { pendingTransactionId: data.pendingTransactionId };
            }
            return this.baseSignTransaction(ctx, userId, walletId, data.protocolId, share, rlpEncodedTxBase64, chainId, isDKLS);
        });
    }
    signHash(_address, _hash) {
        return __awaiter(this, void 0, void 0, function* () {
            throw new Error('not implemented');
        });
    }
    signMessage(ctx, userId, walletId, share, messageBase64, // base64 message
    _sessionCookie, isDKLS) {
        return __awaiter(this, void 0, void 0, function* () {
            const res = yield ctx.client.preSignMessage(userId, walletId, messageBase64);
            if (res.pendingTransactionId) {
                return { pendingTransactionId: res.pendingTransactionId };
            }
            if (ctx.mpcComputationClient && !isDKLS) {
                const signature = (yield signMessageRequest(ctx, userId, walletId, res.protocolId, messageBase64, share)).signature;
                return { signature };
            }
            const signMessageFn = isDKLS ? ParaSignerModule.dklsSignMessage : ParaSignerModule.signMessage;
            const signature = yield signMessageFn(res.protocolId, share, messageBase64, userId);
            if (signature.startsWith('0x')) {
                return { signature: signature.slice(2) };
            }
            return { signature };
        });
    }
    signTransaction(ctx, userId, walletId, share, rlpEncodedTxBase64, // base64 encoding of rlp encoded tx
    chainId, _sessionCookie, isDKLS) {
        return __awaiter(this, void 0, void 0, function* () {
            const { data } = yield ctx.client.signTransaction(userId, walletId, {
                transaction: rlpEncodedTxBase64,
                chainId,
            });
            if (data.pendingTransactionId) {
                return { pendingTransactionId: data.pendingTransactionId };
            }
            return this.baseSignTransaction(ctx, userId, walletId, data.protocolId, share, rlpEncodedTxBase64, chainId, isDKLS);
        });
    }
    ed25519Keygen(ctx, userId, _sessionCookie, _emailProps, type) {
        return __awaiter(this, void 0, void 0, function* () {
            const { walletId, protocolId } = yield ctx.client.createWallet(userId, {
                scheme: 'ED25519',
                type: type !== null && type !== void 0 ? type : 'SOLANA',
            });
            const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
            return { signer, walletId };
        });
    }
    ed25519PreKeygen(ctx, pregenIdentifier, pregenIdentifierType, _sessionCookie, type) {
        return __awaiter(this, void 0, void 0, function* () {
            const { walletId, protocolId } = yield ctx.client.createPregenWallet({
                pregenIdentifier,
                pregenIdentifierType,
                scheme: 'ED25519',
                type: type !== null && type !== void 0 ? type : 'SOLANA',
            });
            const signer = yield ParaSignerModule.ed25519CreateAccount(walletId, protocolId);
            return { signer, walletId };
        });
    }
    ed25519Sign(ctx, userId, walletId, share, base64Bytes, _sessionCookie) {
        return __awaiter(this, void 0, void 0, function* () {
            const res = yield ctx.client.preSignMessage(userId, walletId, base64Bytes, 'ED25519');
            if (res.pendingTransactionId) {
                return { pendingTransactionId: res.pendingTransactionId };
            }
            const base64Sig = yield ParaSignerModule.ed25519Sign(res.protocolId, share, base64Bytes);
            return { signature: base64Sig };
        });
    }
    initializeWorker(_ctx) {
        return __awaiter(this, void 0, void 0, function* () {
            return;
        });
    }
}
