"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientKind = exports.S2Endpoints = exports.BasinEndpointKind = exports.S2Cloud = void 0;
/**
 * S2 cloud environment to connect with.
 */
var S2Cloud;
(function (S2Cloud) {
    /** S2 running on AWS */
    S2Cloud["Aws"] = "aws";
})(S2Cloud || (exports.S2Cloud = S2Cloud = {}));
/**
 * Endpoint for connecting to an S2 basin.
 */
var BasinEndpointKind;
(function (BasinEndpointKind) {
    BasinEndpointKind["ParentZone"] = "ParentZone";
    BasinEndpointKind["Direct"] = "Direct";
})(BasinEndpointKind || (exports.BasinEndpointKind = BasinEndpointKind = {}));
class S2EndpointError extends Error {
    constructor(message) {
        super(message);
        this.name = 'S2EndpointError';
    }
}
/**
 * Endpoints for the S2 environment.
 *
 * You can find the S2 endpoints in our [documentation](https://s2.dev/docs/interface/endpoints)
 */
class S2Endpoints {
    constructor(account, basin) {
        this.account = account;
        this.basin = basin;
    }
    /**
     * Get S2 endpoints for the specified cloud.
     */
    static forCloud(cloud) {
        const authority = `${cloud}.s2.dev`;
        return new S2Endpoints(authority, {
            kind: BasinEndpointKind.ParentZone,
            authority: `b.${cloud}.s2.dev`
        });
    }
    /**
     * Get S2 endpoints for the specified cell.
     */
    static forCell(cloud, cellId) {
        const cellEndpoint = `${cellId}.o.${cloud}.s2.dev`;
        return new S2Endpoints(cellEndpoint, {
            kind: BasinEndpointKind.Direct,
            authority: cellEndpoint
        });
    }
    /**
     * Get S2 endpoints from environment variables.
     *
     * The following environment variables are used:
     * - `S2_CLOUD`: Valid S2 cloud name. Defaults to AWS.
     * - `S2_ACCOUNT_ENDPOINT`: Overrides the account endpoint.
     * - `S2_BASIN_ENDPOINT`: Overrides the basin endpoint. The prefix `"{basin}."` indicates the
     *   basin endpoint is `ParentZone` else `Direct`.
     */
    static fromEnv() {
        let cloud;
        try {
            const cloudEnv = process.env['S2_CLOUD'] || S2Cloud.Aws;
            if (Object.values(S2Cloud).includes(cloudEnv)) {
                cloud = cloudEnv;
            }
            else {
                throw new S2EndpointError(`Invalid S2_CLOUD: ${cloudEnv}`);
            }
        }
        catch (err) {
            const error = err;
            throw new S2EndpointError(`Invalid S2_CLOUD: ${error.message}`);
        }
        const endpoints = S2Endpoints.forCloud(cloud);
        const accountEndpoint = process.env['S2_ACCOUNT_ENDPOINT'];
        if (accountEndpoint !== undefined) {
            if (typeof accountEndpoint !== 'string') {
                throw new S2EndpointError('Invalid S2_ACCOUNT_ENDPOINT: not string');
            }
            endpoints.account = accountEndpoint;
        }
        const basinEndpoint = process.env['S2_BASIN_ENDPOINT'];
        if (basinEndpoint !== undefined) {
            if (typeof basinEndpoint !== 'string') {
                throw new S2EndpointError('Invalid S2_BASIN_ENDPOINT: not string');
            }
            if (basinEndpoint.startsWith('{basin}.')) {
                const parentZone = basinEndpoint.substring(7);
                endpoints.basin = {
                    kind: BasinEndpointKind.ParentZone,
                    authority: parentZone
                };
            }
            else {
                endpoints.basin = {
                    kind: BasinEndpointKind.Direct,
                    authority: basinEndpoint
                };
            }
        }
        return endpoints;
    }
}
exports.S2Endpoints = S2Endpoints;
exports.ClientKind = {
    toAuthority(kind, endpoints) {
        switch (kind.kind) {
            case 'Account':
                return endpoints.account;
            case 'Basin':
                switch (endpoints.basin.kind) {
                    case BasinEndpointKind.ParentZone:
                        return `${kind.basin}.${endpoints.basin.authority}`;
                    case BasinEndpointKind.Direct:
                        return endpoints.basin.authority;
                }
        }
    }
};
//# sourceMappingURL=endpoints.js.map