// SPDX-License-Identifier: Apache-2.0
import { ipV4ToBase64, isIpV4Address } from '../../core/helpers.js';
import { SoloError } from '../../core/errors/solo-error.js';
import { NamespaceName } from '../../types/namespace/namespace-name.js';
export class Address {
    port;
    fqdnOrIpAddress;
    ipAddressV4;
    domainName;
    ipAddressV4Base64;
    constructor(port, fqdnOrIpAddress, ipAddressV4, domainName, ipAddressV4Base64) {
        this.port = port;
        this.fqdnOrIpAddress = fqdnOrIpAddress;
        this.ipAddressV4 = ipAddressV4;
        this.domainName = domainName;
        this.ipAddressV4Base64 = ipAddressV4Base64;
        this.port = port;
        this.fqdnOrIpAddress = fqdnOrIpAddress;
        if (this.fqdnOrIpAddress) {
            if (isIpV4Address(fqdnOrIpAddress)) {
                this.ipAddressV4 = fqdnOrIpAddress;
                this.ipAddressV4Base64 = ipV4ToBase64(fqdnOrIpAddress);
                return;
            }
            else {
                this.domainName = fqdnOrIpAddress;
                return;
            }
        }
        if (this.domainName) {
            this.domainName = domainName;
            return;
        }
        this.ipAddressV4 = ipAddressV4;
        this.ipAddressV4Base64 = ipAddressV4Base64;
        if (this.ipAddressV4 && !this.ipAddressV4Base64) {
            this.ipAddressV4Base64 = ipV4ToBase64(this.ipAddressV4);
        }
        if (this.ipAddressV4Base64 && !this.ipAddressV4) {
            // TODO: implement base64 to IPv4 conversion if needed
            throw new Error('ipAddressV4 must be provided if ipAddressV4Base64 is set');
        }
        if (!this.ipAddressV4 && !this.ipAddressV4Base64) {
            throw new Error('Either domainName or ipAddressV4 must be provided');
        }
    }
    formattedAddress() {
        if (this.domainName) {
            return `${this.domainName}:${this.port}`;
        }
        else if (this.ipAddressV4) {
            return `${this.ipAddressV4}:${this.port}`;
        }
        else {
            throw new Error('Address is not properly initialized');
        }
    }
    hostString() {
        if (this.domainName) {
            return this.domainName;
        }
        else if (this.ipAddressV4) {
            return this.ipAddressV4;
        }
        else {
            throw new Error('Address is not properly initialized');
        }
    }
    static async getExternalAddress(consensusNode, k8, port) {
        return Address.resolveLoadBalancerAddress(consensusNode, k8, port);
    }
    static async resolveLoadBalancerAddress(consensusNode, k8, port) {
        const namespace = NamespaceName.of(consensusNode.namespace);
        try {
            const serviceList = await k8
                .services()
                .list(namespace, [`solo.hedera.com/node-id=${consensusNode.nodeId},solo.hedera.com/type=network-node-svc`]);
            if (serviceList && serviceList.length > 0) {
                const svc = serviceList[0];
                if (!svc.metadata.name.startsWith('network-node')) {
                    throw new SoloError(`Service found is not a network node service: ${svc.metadata.name}`);
                }
                if (svc.spec.type === 'LoadBalancer' &&
                    svc.status?.loadBalancer?.ingress &&
                    svc.status.loadBalancer.ingress.length > 0) {
                    for (let index = 0; index < svc.status.loadBalancer.ingress.length; index++) {
                        const ingress = svc.status.loadBalancer.ingress[index];
                        if (ingress.hostname) {
                            return new Address(port, ingress.hostname);
                        }
                        else if (ingress.ip) {
                            return new Address(port, ingress.ip);
                        }
                    }
                }
            }
        }
        catch {
            // Ignore and use FQDN
        }
        return new Address(port, consensusNode.fullyQualifiedDomainName);
    }
}
//# sourceMappingURL=address.js.map