"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PushAPI = void 0;
const tslib_1 = require("tslib");
const constants_1 = require("../constants");
const PUSH_USER = require("../user");
const PUSH_CHAT = require("../chat");
const helpers_1 = require("../chat/helpers");
const chat_1 = require("./chat");
const profile_1 = require("./profile");
const encryption_1 = require("./encryption");
const user_1 = require("./user");
const PushStream_1 = require("../pushstream/PushStream");
const channel_1 = require("../pushNotification/channel");
const notification_1 = require("../pushNotification/notification");
const config_1 = require("../config");
const helpers_2 = require("../helpers");
class PushAPI {
    constructor(env, account, readMode, alpha, decryptedPgpPvtKey, pgpPublicKey, signer, progressHook, initializationErrors) {
        this.signer = signer;
        this.readMode = readMode;
        this.alpha = alpha;
        this.env = env;
        this.account = account;
        this.decryptedPgpPvtKey = decryptedPgpPvtKey;
        this.pgpPublicKey = pgpPublicKey;
        this.progressHook = progressHook;
        // Instantiate the notification classes
        this.channel = new channel_1.Channel(this.signer, this.env, this.account);
        this.notification = new notification_1.Notification(this.signer, this.env, this.account);
        // Initialize the instances of the four classes
        this.chat = new chat_1.Chat(this.account, this.env, this.alpha, this.decryptedPgpPvtKey, this.signer, this.progressHook);
        this.profile = new profile_1.Profile(this.account, this.env, this.decryptedPgpPvtKey, this.progressHook);
        this.encryption = new encryption_1.Encryption(this.account, this.env, this.decryptedPgpPvtKey, this.pgpPublicKey, this.signer, this.progressHook);
        this.user = new user_1.User(this.account, this.env);
        this.errors = initializationErrors || [];
    }
    static initialize(...args) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let signer;
                let options;
                if (args.length === 1 &&
                    typeof args[0] === 'object' &&
                    'account' in args[0] &&
                    typeof args[0].account === 'string') {
                    // Single options object provided
                    options = args[0];
                }
                else if (args.length === 1) {
                    // Only signer provided
                    [signer] = args;
                }
                else if (args.length === 2) {
                    // Separate signer and options arguments provided
                    [signer, options] = args;
                }
                else {
                    // Handle other cases or throw an error
                    throw new Error('Invalid arguments provided to initialize method.');
                }
                if (!signer && !(options === null || options === void 0 ? void 0 : options.account)) {
                    throw new Error("Either 'signer' or 'account' must be provided.");
                }
                // Default options
                const defaultOptions = {
                    env: constants_1.ENV.STAGING,
                    version: constants_1.default.ENC_TYPE_V3,
                    autoUpgrade: true,
                    account: null,
                };
                // Settings object
                // Default options are overwritten by the options passed in the initialize method
                const settings = Object.assign(Object.assign(Object.assign({}, defaultOptions), options), { version: (options === null || options === void 0 ? void 0 : options.version) || defaultOptions.version, versionMeta: (options === null || options === void 0 ? void 0 : options.versionMeta) || defaultOptions.versionMeta, autoUpgrade: (options === null || options === void 0 ? void 0 : options.autoUpgrade) !== undefined
                        ? options === null || options === void 0 ? void 0 : options.autoUpgrade
                        : defaultOptions.autoUpgrade, alpha: (options === null || options === void 0 ? void 0 : options.alpha) && options.alpha.feature
                        ? options.alpha
                        : config_1.ALPHA_FEATURE_CONFIG[constants_1.PACKAGE_BUILD] });
                let readMode = !signer;
                const initializationErrors = [];
                // Get account
                // Derives account from signer if not provided
                let derivedAccount;
                if (signer) {
                    derivedAccount = yield (0, helpers_1.getAccountAddress)((0, helpers_1.getWallet)({
                        account: settings.account,
                        signer: signer,
                    }));
                }
                else {
                    derivedAccount = options === null || options === void 0 ? void 0 : options.account;
                }
                if (!derivedAccount) {
                    throw new Error('Account could not be derived.');
                }
                let decryptedPGPPrivateKey;
                let pgpPublicKey;
                /**
                 * Decrypt PGP private key
                 * If user exists, decrypts the PGP private key
                 * If user does not exist, creates a new user and returns the decrypted PGP private key
                 */
                const user = yield PUSH_USER.get({
                    account: derivedAccount,
                    env: settings.env,
                });
                if (!readMode) {
                    if (user && user.encryptedPrivateKey) {
                        try {
                            decryptedPGPPrivateKey = yield PUSH_CHAT.decryptPGPKey({
                                encryptedPGPPrivateKey: user.encryptedPrivateKey,
                                signer: signer,
                                toUpgrade: settings.autoUpgrade,
                                additionalMeta: settings.versionMeta,
                                progressHook: settings.progressHook,
                                env: settings.env,
                            });
                        }
                        catch (error) {
                            const decryptionError = 'Error decrypting PGP private key ...swiching to Guest mode';
                            initializationErrors.push({
                                type: 'ERROR',
                                message: decryptionError,
                            });
                            console.error(decryptionError);
                            if ((0, helpers_2.isValidCAIP10NFTAddress)(derivedAccount)) {
                                const nftDecryptionError = 'NFT Account Detected. If this NFT was recently transferred to you, please ensure you have received the correct password from the previous owner. Alternatively, you can reinitialize for a fresh start. Please be aware that reinitialization will result in the loss of all previous account data.';
                                initializationErrors.push({
                                    type: 'WARN',
                                    message: nftDecryptionError,
                                });
                                console.warn(nftDecryptionError);
                            }
                            readMode = true;
                        }
                        pgpPublicKey = user.publicKey;
                    }
                    else {
                        const newUser = yield PUSH_USER.create({
                            env: settings.env,
                            account: derivedAccount,
                            signer,
                            version: settings.version,
                            additionalMeta: settings.versionMeta,
                            origin: settings.origin,
                            progressHook: settings.progressHook,
                        });
                        decryptedPGPPrivateKey = newUser.decryptedPrivateKey;
                        pgpPublicKey = newUser.publicKey;
                    }
                }
                // Initialize PushAPI instance
                const api = new PushAPI(settings.env, derivedAccount, readMode, settings.alpha, decryptedPGPPrivateKey, pgpPublicKey, signer, settings.progressHook, initializationErrors);
                return api;
            }
            catch (error) {
                console.error('Error initializing PushAPI:', error);
                throw error; // or handle it more gracefully if desired
            }
        });
    }
    /**
     * This method is used to reinitialize the PushAPI instance
     * @notice - This method should only be used for fresh start of NFT accounts
     * @notice - All data will be lost after reinitialization
     */
    reinitialize(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const newUser = yield PUSH_USER.create({
                env: this.env,
                account: this.account,
                signer: this.signer,
                additionalMeta: options.versionMeta,
                progressHook: this.progressHook,
            });
            this.decryptedPgpPvtKey = newUser.decryptedPrivateKey;
            this.pgpPublicKey = newUser.publicKey;
            this.readMode = false;
            this.errors = [];
            // Initialize the instances of the four classes
            this.chat = new chat_1.Chat(this.account, this.env, this.alpha, this.decryptedPgpPvtKey, this.signer, this.progressHook);
            this.profile = new profile_1.Profile(this.account, this.env, this.decryptedPgpPvtKey, this.progressHook);
            this.encryption = new encryption_1.Encryption(this.account, this.env, this.decryptedPgpPvtKey, this.pgpPublicKey, this.signer, this.progressHook);
        });
    }
    initStream(listen, options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (this.stream) {
                throw new Error('Stream is already initialized.');
            }
            this.stream = yield PushStream_1.PushStream.initialize(this.account, listen, this.env, this.decryptedPgpPvtKey, this.progressHook, this.signer, options);
            return this.stream;
        });
    }
    info(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const accountToUse = (options === null || options === void 0 ? void 0 : options.overrideAccount) || this.account;
            return yield PUSH_USER.get({
                account: accountToUse,
                env: this.env,
            });
        });
    }
    static ensureSignerMessage() {
        return 'Operation not allowed in read-only mode. Signer is required.';
    }
}
exports.PushAPI = PushAPI;
//# sourceMappingURL=PushAPI.js.map