import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
import { KeetaAnchorCertificateRequiredError, KeetaAnchorUserError, KeetaAnchorUserValidationError } from '../../lib/error.js';
export * from './common.generated.js';
export const USERNAME_DELIMITER = '$';
export const USERNAME_MIN_LENGTH = 1;
export const USERNAME_MAX_LENGTH = 256;
export function validateUsernameDefault(username, options = {}) {
    const fieldPath = options.fieldPath ?? 'username';
    if (username.length > USERNAME_MAX_LENGTH || username.length < USERNAME_MIN_LENGTH) {
        throw (new KeetaAnchorUserValidationError({
            fields: [
                {
                    path: fieldPath,
                    message: `Username must be between ${USERNAME_MIN_LENGTH}-${USERNAME_MAX_LENGTH} characters`,
                    receivedValue: username
                }
            ]
        }));
    }
    if (username.includes(USERNAME_DELIMITER)) {
        throw (new KeetaAnchorUserValidationError({
            fields: [
                {
                    path: fieldPath,
                    message: `Username must not contain "${USERNAME_DELIMITER}" character`,
                    receivedValue: username
                }
            ]
        }));
    }
    const isUSAscii = /^[\x20-\x7E]*$/.test(username);
    if (!isUSAscii) {
        throw (new KeetaAnchorUserValidationError({
            fields: [
                {
                    path: fieldPath,
                    message: 'Username must contain only US ASCII characters',
                    receivedValue: username
                }
            ]
        }));
    }
    if (options.pattern !== undefined) {
        const pattern = typeof options.pattern === 'string' ? new RegExp(options.pattern) : options.pattern;
        pattern.lastIndex = 0;
        if (!pattern.test(username)) {
            throw (new KeetaAnchorUserValidationError({
                fields: [
                    {
                        path: fieldPath,
                        message: 'Provider issued name does not match required pattern',
                        receivedValue: username,
                        expected: pattern.source
                    }
                ]
            }));
        }
    }
}
;
;
;
function assertSegment(value, type) {
    const trimmed = value.trim();
    if (trimmed.length === 0) {
        throw (new Error(`Globally identifiable username ${type} must not be empty`));
    }
    if (trimmed.includes(USERNAME_DELIMITER)) {
        throw (new Error(`Globally identifiable username ${type} must not contain "${USERNAME_DELIMITER}"`));
    }
    return (trimmed);
}
export function formatGloballyIdentifiableUsername(providerIssuedName, providerID) {
    const safeName = assertSegment(providerIssuedName, 'provider issued unique name');
    const safeProviderID = assertSegment(providerID, 'provider ID');
    return (`${safeName}${USERNAME_DELIMITER}${safeProviderID}`);
}
function attemptParseGloballyIdentifiableUsername(input) {
    if (typeof input !== 'string') {
        throw (new Error('Globally identifiable username must be a string'));
    }
    const trimmed = input.trim();
    if (trimmed.length !== input.length) {
        throw (new Error('Globally identifiable username must not have leading or trailing whitespace'));
    }
    const separatorIndex = trimmed.lastIndexOf(USERNAME_DELIMITER);
    if (separatorIndex === -1) {
        throw (new Error(`Globally identifiable username must contain "${USERNAME_DELIMITER}" separator`));
    }
    const providerIssuedNameSegment = trimmed.slice(0, separatorIndex);
    const providerIDSegment = trimmed.slice(separatorIndex + 1);
    const username = assertSegment(providerIssuedNameSegment, 'provider issued unique name');
    const providerID = assertSegment(providerIDSegment, 'provider ID');
    return ({
        username,
        providerID
    });
}
export function isGloballyIdentifiableUsername(input) {
    try {
        attemptParseGloballyIdentifiableUsername(input);
        return (true);
    }
    catch {
        return (false);
    }
}
export function parseGloballyIdentifiableUsername(input) {
    return (attemptParseGloballyIdentifiableUsername(input));
}
// Namespace for the Username Anchor signable claims
const usernameNamespace = 'c26e65bf-ad9f-4000-bc81-12c31dc86b8b';
export function getUsernameClaimSignable(request) {
    return ([
        usernameNamespace,
        'CLAIM_USERNAME',
        request.username,
        request.account.publicKeyString.get(),
        // Transfer data
        request.transfer?.from ?? 0,
        request.transfer?.signed.signature ?? 0,
        request.transfer?.signed.nonce ?? 0,
        request.transfer?.signed.timestamp ?? 0
    ]);
}
export function getUsernameTransferSignable(payload) {
    return ([
        usernameNamespace,
        'TRANSFER_USERNAME',
        payload.username,
        payload.from,
        payload.to
    ]);
}
export function getUsernameReleaseSignable(payload) {
    return ([
        usernameNamespace,
        'RELEASE_USERNAME',
        payload.account
    ]);
}
class KeetaUsernameAnchorUsernameAlreadyTakenError extends KeetaAnchorUserError {
    static name = 'KeetaUsernameAnchorUsernameAlreadyTakenError';
    KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID;
    static KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID = 'e5bba4dd-0217-4d96-8f66-2b9a61069c11';
    logLevel = 'INFO';
    username;
    constructor(properties, message) {
        super(message ?? `Username ${properties.username} already taken`);
        this.statusCode = 409;
        Object.defineProperty(this, 'KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID', {
            value: KeetaUsernameAnchorUsernameAlreadyTakenError.KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID,
            enumerable: false
        });
        this.username = properties.username;
    }
    static isInstance(input) {
        return (this.hasPropWithValue(input, 'KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID', KeetaUsernameAnchorUsernameAlreadyTakenError.KeetaUsernameAnchorUsernameAlreadyTakenErrorObjectTypeID));
    }
    toJSON() {
        return ({
            ...super.toJSON(),
            username: this.username
        });
    }
    static async fromJSON(input) {
        const { message, other } = this.extractErrorProperties(input, this);
        if (!('username' in other) || typeof other.username !== 'string') {
            throw (new Error('Invalid KeetaUsernameAnchorUsernameAlreadyTakenError JSON object: missing or invalid username'));
        }
        const error = new this({ username: other.username }, message);
        error.restoreFromJSON(other);
        return (error);
    }
}
class KeetaUsernameAnchorUserNotFoundError extends KeetaAnchorUserError {
    static name = 'KeetaUsernameAnchorUserNotFoundError';
    KeetaUsernameAnchorUserNotFoundErrorObjectTypeID;
    static KeetaUsernameAnchorUserNotFoundErrorObjectTypeID = 'd4831db5-ca33-4c21-9780-ec86929f2e4c';
    logLevel = 'INFO';
    username;
    account;
    constructor(properties, message) {
        super(message ?? `${properties.username ?? properties.account?.publicKeyString.get() ?? '<UNKNOWN>'} not found`);
        this.statusCode = 404;
        Object.defineProperty(this, 'KeetaUsernameAnchorUserNotFoundErrorObjectTypeID', {
            value: KeetaUsernameAnchorUserNotFoundError.KeetaUsernameAnchorUserNotFoundErrorObjectTypeID,
            enumerable: false
        });
        this.username = properties.username;
        this.account = properties.account;
    }
    static isInstance(input) {
        return (this.hasPropWithValue(input, 'KeetaUsernameAnchorUserNotFoundErrorObjectTypeID', KeetaUsernameAnchorUserNotFoundError.KeetaUsernameAnchorUserNotFoundErrorObjectTypeID));
    }
    toJSON() {
        return ({
            ...super.toJSON(),
            username: this.username
        });
    }
    static async fromJSON(input) {
        const { message, other } = this.extractErrorProperties(input, this);
        const properties = {};
        if ('username' in other) {
            if (typeof other.username !== 'string') {
                throw (new Error('Invalid KeetaUsernameAnchorUserNotFoundError JSON object: missing or invalid username'));
            }
            properties.username = other.username;
        }
        if ('account' in other && other.account) {
            if (typeof other.account !== 'string' && !(KeetaNetLib.Account.isInstance(other.account))) {
                throw (new Error('Invalid KeetaUsernameAnchorUserNotFoundError JSON object: account must be a string or KeetaNet Account object'));
            }
            properties.account = KeetaNetLib.Account.toAccount(other.account);
        }
        const error = new this(properties, message);
        error.restoreFromJSON(other);
        return (error);
    }
}
export const Errors = {
    UsernameAlreadyTaken: KeetaUsernameAnchorUsernameAlreadyTakenError,
    UserNotFound: KeetaUsernameAnchorUserNotFoundError,
    CertificateRequired: KeetaAnchorCertificateRequiredError
};
//# sourceMappingURL=common.js.map