import { XMLParser } from "fast-xml-parser";
import { Resource } from "../../resource.js";
import { ignore } from "../../util/ignore.js";
import { logger } from "../../util/logger.js";
import { mergeTimeoutConfig, waitForResourceState, } from "../../util/timeout.js";
import { callEC2Api, createEC2Client } from "./utils.js";
/**
 * AWS NAT Gateway Resource
 *
 * Creates and manages NAT Gateways that provide outbound internet access
 * for instances in private subnets. Automatically allocates an Elastic IP
 * if one is not provided. NAT Gateways are slow resources that can take
 * up to 10 minutes to become available.
 *
 * Supports AWS credential overrides at the resource level, allowing you to deploy NAT Gateways
 * to different AWS accounts or regions than the default scope configuration.
 *
 * @example
 * ```typescript
 * // Create a NAT Gateway with automatic Elastic IP allocation
 * const natGateway = await NatGateway("main-nat", {
 *   subnet: publicSubnet,
 *   tags: {
 *     Name: "main-nat-gateway",
 *     Environment: "production"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create NAT Gateway with AWS credential overrides
 * const crossAccountNat = await NatGateway("cross-account-nat", {
 *   subnet: publicSubnet,
 *   // Override AWS credentials for this specific resource
 *   region: "us-east-1",
 *   profile: "production-account",
 *   tags: {
 *     Name: "cross-account-nat-gateway",
 *     Environment: "production"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create NAT Gateway in different region with role assumption
 * const multiRegionNat = await NatGateway("multi-region-nat", {
 *   subnet: euPublicSubnet,
 *   region: "eu-west-1",
 *   roleArn: "arn:aws:iam::123456789012:role/CrossRegionRole",
 *   roleSessionName: "nat-gateway-deployment",
 *   tags: {
 *     Name: "eu-nat-gateway",
 *     Region: "europe"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create NAT Gateway with explicit credentials
 * const explicitCredsNat = await NatGateway("explicit-creds-nat", {
 *   subnet: testPublicSubnet,
 *   accessKeyId: alchemy.secret("AKIAIOSFODNN7EXAMPLE"),
 *   secretAccessKey: alchemy.secret("wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"),
 *   region: "us-west-2",
 *   tags: {
 *     Name: "explicit-credentials-nat",
 *     Purpose: "testing"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create a NAT Gateway with existing Elastic IP
 * const natGateway = await NatGateway("custom-nat", {
 *   subnet: "subnet-12345678",
 *   allocationId: "eipalloc-12345678",
 *   connectivityType: "public",
 *   tags: {
 *     Name: "custom-nat-gateway"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create a private NAT Gateway (for VPC-to-VPC communication)
 * const privateNat = await NatGateway("private-nat", {
 *   subnet: privateSubnet,
 *   connectivityType: "private",
 *   tags: {
 *     Name: "private-nat-gateway",
 *     Type: "internal"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Create a NAT Gateway with custom timeout configuration
 * const slowNat = await NatGateway("slow-nat", {
 *   subnet: publicSubnet,
 *   timeout: {
 *     maxAttempts: 180, // Wait up to 15 minutes
 *     delayMs: 5000     // Check every 5 seconds
 *   },
 *   tags: {
 *     Name: "slow-nat-gateway"
 *   }
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Multi-account deployment with scope-level and resource-level overrides
 * await alchemy.run("production", {
 *   aws: { region: "us-west-2", profile: "main-account" }
 * }, async () => {
 *   // This NAT Gateway uses scope credentials (main-account, us-west-2)
 *   const mainNat = await NatGateway("main-nat", {
 *     subnet: mainPublicSubnet,
 *     tags: { Name: "main-account-nat" }
 *   });
 *
 *   // This NAT Gateway overrides to use different account
 *   const crossAccountNat = await NatGateway("cross-account-nat", {
 *     subnet: crossPublicSubnet,
 *     profile: "secondary-account",
 *     region: "us-east-1", // Also override region
 *     tags: { Name: "secondary-account-nat" }
 *   });
 * });
 * ```
 *
 * @example
 * ```typescript
 * // Use NAT Gateway in route table for private subnet internet access
 * const privateRoute = await Route("private-internet", {
 *   routeTable: privateRouteTable,
 *   destinationCidrBlock: "0.0.0.0/0",
 *   natGateway: natGateway,
 *   tags: {
 *     Name: "private-to-internet"
 *   }
 * });
 * ```
 */
export const NatGateway = Resource("aws::NatGateway", async function (_id, props) {
    // Create EC2 client with credential resolution handled internally
    const client = await createEC2Client(props);
    const subnetId = typeof props.subnet === "string" ? props.subnet : props.subnet.subnetId;
    const timeoutConfig = mergeTimeoutConfig(NAT_GATEWAY_TIMEOUT, props.timeout);
    if (this.phase === "delete") {
        if (this.output?.natGatewayId) {
            logger.log(`🗑️ Deleting NAT Gateway: ${this.output.natGatewayId}`);
            // Delete NAT Gateway if it exists
            await ignore("InvalidNatGatewayID.NotFound", async () => {
                await callEC2Api(client, "DeleteNatGateway", parseNatGatewayXmlResponse, convertDeleteNatGatewayParamsToAwsFormat({
                    NatGatewayId: this.output.natGatewayId,
                }));
            });
            // Wait for NAT Gateway to be deleted AND network interfaces to be cleaned up
            logger.log(`  Waiting for NAT Gateway ${this.output.natGatewayId} to be fully deleted...`);
            await waitForNatGatewayFullyDeleted(this.output.natGatewayId, timeoutConfig, props);
            logger.log(`  ✅ NAT Gateway ${this.output.natGatewayId} deletion completed`);
            // Release Elastic IP if we created it and it exists
            if (this.output.createdElasticIp && this.output.allocationId) {
                logger.log(`  Releasing Elastic IP: ${this.output.allocationId}`);
                await ignore(["InvalidAllocationID.NotFound", "InvalidAddress.NotFound"], async () => {
                    await callEC2Api(client, "ReleaseAddress", parseNatGatewayXmlResponse, convertReleaseAddressParamsToAwsFormat({
                        AllocationId: this.output.allocationId,
                    }));
                });
                // Wait for the EIP to be fully released
                await waitForEipReleased(this.output.allocationId, timeoutConfig, props);
                logger.log(`  ✅ Elastic IP ${this.output.allocationId} released successfully`);
            }
        }
        return this.destroy();
    }
    let natGateway;
    let allocationId = props.allocationId;
    let createdElasticIp = false;
    let publicIp;
    if (this.phase === "update" && this.output?.natGatewayId) {
        // Get existing NAT Gateway
        const response = await callEC2Api(client, "DescribeNatGateways", parseNatGatewayXmlResponse, convertDescribeNatGatewaysParamsToAwsFormat({
            NatGatewayIds: [this.output.natGatewayId],
        }));
        if (!response.NatGateways?.[0]) {
            throw new Error(`NAT Gateway ${this.output.natGatewayId} not found`);
        }
        natGateway = response.NatGateways[0];
        allocationId = this.output.allocationId;
        createdElasticIp = this.output.createdElasticIp;
        publicIp = this.output.publicIp;
    }
    else {
        // Allocate Elastic IP if not provided
        if (!allocationId) {
            const eipParams = {
                Domain: "vpc",
            };
            // Add tags if specified
            if (props.tags) {
                eipParams.TagSpecifications = [
                    {
                        ResourceType: "elastic-ip",
                        Tags: Object.entries(props.tags).map(([key, value]) => ({
                            Key: `${key}-eip`,
                            Value: value,
                        })),
                    },
                ];
            }
            const eipResponse = await callEC2Api(client, "AllocateAddress", parseNatGatewayXmlResponse, convertAllocateAddressParamsToAwsFormat(eipParams));
            if (!eipResponse.AllocationId) {
                throw new Error("Failed to allocate Elastic IP");
            }
            allocationId = eipResponse.AllocationId;
            publicIp = eipResponse.PublicIp;
            createdElasticIp = true;
        }
        else {
            // Get public IP of existing allocation
            const addressResponse = await callEC2Api(client, "DescribeAddresses", parseNatGatewayXmlResponse, convertDescribeAddressesParamsToAwsFormat({
                AllocationIds: [allocationId],
            }));
            publicIp = addressResponse.Addresses?.[0]?.PublicIp;
        }
        // Create NAT Gateway
        const createParams = {
            SubnetId: subnetId,
            AllocationId: allocationId,
            ConnectivityType: props.connectivityType || "public",
        };
        // Add tags if specified
        if (props.tags) {
            createParams.TagSpecifications = [
                {
                    ResourceType: "natgateway",
                    Tags: Object.entries(props.tags).map(([key, value]) => ({
                        Key: key,
                        Value: value,
                    })),
                },
            ];
        }
        const response = await callEC2Api(client, "CreateNatGateway", parseNatGatewayXmlResponse, convertCreateNatGatewayParamsToAwsFormat(createParams));
        if (!response.NatGateway) {
            throw new Error("Failed to create NAT Gateway");
        }
        natGateway = response.NatGateway;
        // Wait for NAT Gateway to be available
        await waitForNatGatewayAvailable(natGateway.NatGatewayId, timeoutConfig, props);
    }
    const result = {
        natGatewayId: natGateway.NatGatewayId,
        subnetId: natGateway.SubnetId,
        vpcId: natGateway.VpcId,
        state: natGateway.State,
        allocationId: allocationId,
        publicIp,
        privateIp: natGateway.NatGatewayAddresses?.[0]?.PrivateIp,
        createdElasticIp,
        ...props,
        subnet: subnetId,
    };
    return result;
});
/**
 * Wait for NAT Gateway to be in available state
 */
async function waitForNatGatewayAvailable(natGatewayId, timeoutConfig, credentials) {
    const checkFunction = async () => {
        const client = await createEC2Client(credentials);
        const response = await callEC2Api(client, "DescribeNatGateways", parseNatGatewayXmlResponse, convertDescribeNatGatewaysParamsToAwsFormat({
            NatGatewayIds: [natGatewayId],
        }));
        return response.NatGateways?.[0];
    };
    const isReady = (natGateway) => {
        // Check for non-retryable failure states
        if (natGateway?.State === "failed") {
            throw new NatGatewayNonRetryableError(`NAT Gateway ${natGatewayId} failed to create`);
        }
        return natGateway?.State === "available";
    };
    await waitForResourceState(checkFunction, isReady, timeoutConfig, natGatewayId, "NAT Gateway", "is now available");
}
/**
 * Wait for NAT Gateway to be deleted
 */
async function waitForNatGatewayDeleted(natGatewayId, timeoutConfig, credentials) {
    const checkFunction = async () => {
        try {
            const client = await createEC2Client(credentials);
            const response = await callEC2Api(client, "DescribeNatGateways", parseNatGatewayXmlResponse, convertDescribeNatGatewaysParamsToAwsFormat({
                NatGatewayIds: [natGatewayId],
            }));
            return response.NatGateways?.[0];
        }
        catch (error) {
            // If NAT Gateway is not found, it's been deleted - return undefined
            if (error.code === "InvalidNatGatewayID.NotFound" ||
                error.code === "InvalidNatGateway.NotFound" ||
                error.code === "NatGatewayNotFound") {
                return undefined;
            }
            throw error;
        }
    };
    const isReady = (natGateway) => {
        // NAT Gateway is deleted if it doesn't exist or is in deleted state
        return !natGateway || natGateway.State === "deleted";
    };
    await waitForResourceState(checkFunction, isReady, timeoutConfig, natGatewayId, "NAT Gateway", "deletion completed");
}
/**
 * Parse XML response for DescribeNetworkInterfaces
 */
function parseDescribeNetworkInterfacesResponse(xmlText) {
    const parser = new XMLParser({
        ignoreAttributes: true,
        parseAttributeValue: true,
        parseTagValue: true,
        trimValues: true,
    });
    const parsed = parser.parse(xmlText);
    const result = { NetworkInterfaces: [] };
    if (parsed.DescribeNetworkInterfacesResponse) {
        const networkInterfaceSet = parsed.DescribeNetworkInterfacesResponse.networkInterfaceSet;
        if (networkInterfaceSet?.item) {
            const items = Array.isArray(networkInterfaceSet.item)
                ? networkInterfaceSet.item
                : [networkInterfaceSet.item];
            result.NetworkInterfaces = items.map((item) => ({
                NetworkInterfaceId: item.networkInterfaceId,
                Description: item.description,
                Status: item.status,
            }));
        }
    }
    return result;
}
/**
 * Wait for an Elastic IP to be released.
 */
async function waitForEipReleased(allocationId, timeoutConfig, credentials) {
    const checkFunction = async () => {
        try {
            const eipClient = await createEC2Client(credentials);
            const addressResponse = await callEC2Api(eipClient, "DescribeAddresses", parseNatGatewayXmlResponse, convertDescribeAddressesParamsToAwsFormat({
                AllocationIds: [allocationId],
            }));
            return addressResponse.Addresses?.[0];
        }
        catch (error) {
            if (error.code === "InvalidAllocationID.NotFound" ||
                error.code === "InvalidAddress.NotFound") {
                return undefined;
            }
            throw error;
        }
    };
    const isReady = (address) => {
        return !address;
    };
    await waitForResourceState(checkFunction, isReady, timeoutConfig, allocationId, "Elastic IP", "to be released");
}
/**
 * Wait for NAT Gateway to be fully deleted including network interface cleanup
 */
async function waitForNatGatewayFullyDeleted(natGatewayId, timeoutConfig, credentials) {
    // First wait for the NAT Gateway itself to be deleted
    await waitForNatGatewayDeleted(natGatewayId, timeoutConfig, credentials);
    // Then wait for network interfaces to be cleaned up
    const checkNetworkInterfaces = async () => {
        try {
            const client = await createEC2Client(credentials);
            const response = await callEC2Api(client, "DescribeNetworkInterfaces", parseDescribeNetworkInterfacesResponse, {
                "Filter.1.Name": "description",
                "Filter.1.Value.1": `Interface for NAT Gateway ${natGatewayId}`,
            });
            return response.NetworkInterfaces || [];
        }
        catch (error) {
            // If we can't check network interfaces, assume cleanup is complete
            logger.log(`  Could not check network interfaces for NAT Gateway ${natGatewayId}, assuming cleanup complete`, error);
            return [];
        }
    };
    const isNetworkInterfacesCleanedUp = (networkInterfaces) => {
        if (networkInterfaces.length > 0) {
            logger.log(`  NAT Gateway ${natGatewayId} still has ${networkInterfaces.length} network interfaces, waiting for cleanup...`);
            return false;
        }
        return true;
    };
    await waitForResourceState(checkNetworkInterfaces, isNetworkInterfacesCleanedUp, timeoutConfig, natGatewayId, "NAT Gateway network interfaces", "cleanup completed");
}
/**
 * Non-retryable error for NAT Gateway operations
 */
export class NatGatewayNonRetryableError extends Error {
    constructor(message) {
        super(message);
        this.name = "NatGatewayNonRetryableError";
    }
}
/**
 * NAT Gateway timeout constants
 */
export const NAT_GATEWAY_TIMEOUT = {
    maxAttempts: 120, // NAT Gateways are slow resources - can take up to 10 minutes
    delayMs: 5000, // Check every 5 seconds
};
/**
 * Parse XML responses specifically for NAT Gateway operations
 */
function parseNatGatewayXmlResponse(xmlText) {
    const parser = new XMLParser({
        ignoreAttributes: true,
        parseAttributeValue: true,
        parseTagValue: true,
        trimValues: true,
    });
    const parsed = parser.parse(xmlText);
    const result = {};
    // Parse CreateNatGatewayResponse
    if (parsed.CreateNatGatewayResponse) {
        const natGateway = parsed.CreateNatGatewayResponse
            .natGateway;
        if (natGateway) {
            const addresses = natGateway.natGatewayAddressSet?.item
                ? Array.isArray(natGateway.natGatewayAddressSet.item)
                    ? natGateway.natGatewayAddressSet.item
                    : [natGateway.natGatewayAddressSet.item]
                : [];
            const tags = natGateway.tagSet?.item
                ? Array.isArray(natGateway.tagSet.item)
                    ? natGateway.tagSet.item
                    : [natGateway.tagSet.item]
                : [];
            result.NatGateway = {
                NatGatewayId: natGateway.natGatewayId,
                SubnetId: natGateway.subnetId,
                VpcId: natGateway.vpcId,
                State: natGateway.state,
                ConnectivityType: natGateway.connectivityType,
                NatGatewayAddresses: addresses.map((address) => ({
                    AllocationId: address.allocationId,
                    NetworkInterfaceId: address.networkInterfaceId,
                    PrivateIp: address.privateIp,
                    PublicIp: address.publicIp,
                })),
                Tags: tags.map((tag) => ({
                    Key: tag.key,
                    Value: tag.value,
                })),
                CreateTime: natGateway.createTime,
                DeleteTime: natGateway.deleteTime,
                FailureCode: natGateway.failureCode,
                FailureMessage: natGateway.failureMessage,
            };
        }
    }
    // Parse DescribeNatGatewaysResponse
    if (parsed.DescribeNatGatewaysResponse) {
        const natGatewaySet = parsed.DescribeNatGatewaysResponse.natGatewaySet;
        if (natGatewaySet?.item) {
            const natGateways = Array.isArray(natGatewaySet.item)
                ? natGatewaySet.item
                : [natGatewaySet.item];
            result.NatGateways = natGateways.map((natGateway) => {
                const addresses = natGateway.natGatewayAddressSet?.item
                    ? Array.isArray(natGateway.natGatewayAddressSet.item)
                        ? natGateway.natGatewayAddressSet.item
                        : [natGateway.natGatewayAddressSet.item]
                    : [];
                const tags = natGateway.tagSet?.item
                    ? Array.isArray(natGateway.tagSet.item)
                        ? natGateway.tagSet.item
                        : [natGateway.tagSet.item]
                    : [];
                return {
                    NatGatewayId: natGateway.natGatewayId,
                    SubnetId: natGateway.subnetId,
                    VpcId: natGateway.vpcId,
                    State: natGateway.state,
                    ConnectivityType: natGateway.connectivityType,
                    NatGatewayAddresses: addresses.map((address) => ({
                        AllocationId: address.allocationId,
                        NetworkInterfaceId: address.networkInterfaceId,
                        PrivateIp: address.privateIp,
                        PublicIp: address.publicIp,
                    })),
                    Tags: tags.map((tag) => ({
                        Key: tag.key,
                        Value: tag.value,
                    })),
                    CreateTime: natGateway.createTime,
                    DeleteTime: natGateway.deleteTime,
                    FailureCode: natGateway.failureCode,
                    FailureMessage: natGateway.failureMessage,
                };
            });
        }
        else {
            result.NatGateways = [];
        }
    }
    // Parse AllocateAddressResponse (for EIP allocation)
    if (parsed.AllocateAddressResponse) {
        result.AllocationId = parsed.AllocateAddressResponse.allocationId;
        result.PublicIp = parsed.AllocateAddressResponse.publicIp;
    }
    // Parse DescribeAddressesResponse (for EIP lookup)
    if (parsed.DescribeAddressesResponse) {
        const addressesSet = parsed.DescribeAddressesResponse.addressesSet;
        if (addressesSet?.item) {
            const addresses = Array.isArray(addressesSet.item)
                ? addressesSet.item
                : [addressesSet.item];
            result.Addresses = addresses.map((address) => ({
                AllocationId: address.allocationId,
                PublicIp: address.publicIp,
                PrivateIpAddress: address.privateIpAddress,
                Domain: address.domain,
            }));
        }
        else {
            result.Addresses = [];
        }
    }
    // Handle success responses
    if (parsed.DeleteNatGatewayResponse || parsed.ReleaseAddressResponse) {
        result.success = true;
    }
    return result;
}
/**
 * Helper functions to convert typed parameters to AWS API format
 */
function convertCreateNatGatewayParamsToAwsFormat(params) {
    const awsParams = {
        SubnetId: params.SubnetId,
    };
    if (params.AllocationId !== undefined) {
        awsParams.AllocationId = params.AllocationId;
    }
    if (params.ConnectivityType !== undefined) {
        awsParams.ConnectivityType = params.ConnectivityType;
    }
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    if (params.ClientToken !== undefined) {
        awsParams.ClientToken = params.ClientToken;
    }
    // Handle TagSpecifications
    if (params.TagSpecifications) {
        params.TagSpecifications.forEach((tagSpec, specIndex) => {
            const specNum = specIndex + 1;
            awsParams[`TagSpecification.${specNum}.ResourceType`] =
                tagSpec.ResourceType;
            tagSpec.Tags.forEach((tag, tagIndex) => {
                const tagNum = tagIndex + 1;
                awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Key`] = tag.Key;
                awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Value`] =
                    tag.Value;
            });
        });
    }
    return awsParams;
}
function convertDescribeNatGatewaysParamsToAwsFormat(params) {
    const awsParams = {};
    if (params.NatGatewayIds) {
        params.NatGatewayIds.forEach((id, index) => {
            awsParams[`NatGatewayId.${index + 1}`] = id;
        });
    }
    if (params.Filters) {
        params.Filters.forEach((filter, filterIndex) => {
            const filterNum = filterIndex + 1;
            awsParams[`Filter.${filterNum}.Name`] = filter.Name;
            filter.Values.forEach((value, valueIndex) => {
                awsParams[`Filter.${filterNum}.Value.${valueIndex + 1}`] = value;
            });
        });
    }
    if (params.NextToken !== undefined) {
        awsParams.NextToken = params.NextToken;
    }
    if (params.MaxResults !== undefined) {
        awsParams.MaxResults = params.MaxResults.toString();
    }
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    return awsParams;
}
function convertDeleteNatGatewayParamsToAwsFormat(params) {
    const awsParams = {
        NatGatewayId: params.NatGatewayId,
    };
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    return awsParams;
}
function convertAllocateAddressParamsToAwsFormat(params) {
    const awsParams = {};
    if (params.Domain !== undefined) {
        awsParams.Domain = params.Domain;
    }
    if (params.Address !== undefined) {
        awsParams.Address = params.Address;
    }
    if (params.PublicIpv4Pool !== undefined) {
        awsParams.PublicIpv4Pool = params.PublicIpv4Pool;
    }
    if (params.NetworkBorderGroup !== undefined) {
        awsParams.NetworkBorderGroup = params.NetworkBorderGroup;
    }
    if (params.CustomerOwnedIpv4Pool !== undefined) {
        awsParams.CustomerOwnedIpv4Pool = params.CustomerOwnedIpv4Pool;
    }
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    // Handle TagSpecifications
    if (params.TagSpecifications) {
        params.TagSpecifications.forEach((tagSpec, specIndex) => {
            const specNum = specIndex + 1;
            awsParams[`TagSpecification.${specNum}.ResourceType`] =
                tagSpec.ResourceType;
            tagSpec.Tags.forEach((tag, tagIndex) => {
                const tagNum = tagIndex + 1;
                awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Key`] = tag.Key;
                awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Value`] =
                    tag.Value;
            });
        });
    }
    return awsParams;
}
function convertDescribeAddressesParamsToAwsFormat(params) {
    const awsParams = {};
    if (params.AllocationIds) {
        params.AllocationIds.forEach((id, index) => {
            awsParams[`AllocationId.${index + 1}`] = id;
        });
    }
    if (params.PublicIps) {
        params.PublicIps.forEach((ip, index) => {
            awsParams[`PublicIp.${index + 1}`] = ip;
        });
    }
    if (params.Filters) {
        params.Filters.forEach((filter, filterIndex) => {
            const filterNum = filterIndex + 1;
            awsParams[`Filter.${filterNum}.Name`] = filter.Name;
            filter.Values.forEach((value, valueIndex) => {
                awsParams[`Filter.${filterNum}.Value.${valueIndex + 1}`] = value;
            });
        });
    }
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    return awsParams;
}
function convertReleaseAddressParamsToAwsFormat(params) {
    const awsParams = {};
    if (params.AllocationId !== undefined) {
        awsParams.AllocationId = params.AllocationId;
    }
    if (params.PublicIp !== undefined) {
        awsParams.PublicIp = params.PublicIp;
    }
    if (params.NetworkBorderGroup !== undefined) {
        awsParams.NetworkBorderGroup = params.NetworkBorderGroup;
    }
    if (params.DryRun !== undefined) {
        awsParams.DryRun = params.DryRun.toString();
    }
    return awsParams;
}
//# sourceMappingURL=nat-gateway.js.map