# This file is automatically generated by botocraft.  Do not edit directly.
# pylint: disable=anomalous-backslash-in-string,unsubscriptable-object,line-too-long,arguments-differ,arguments-renamed,unused-import,redefined-outer-name
# pyright: reportUnusedImport=false
# mypy: disable-error-code="index, override, assignment, union-attr, misc"
from collections import OrderedDict
from datetime import datetime
from functools import cached_property
from typing import Any, ClassVar, Dict, List, Literal, Optional, Type, cast

from botocraft.mixins.elb import (ClassicELBManagerMixin, ClassicELBModelMixin,
                                  add_attributes_for_get,
                                  add_attributes_for_list, add_tags_for_get,
                                  add_tags_for_list)
from botocraft.mixins.tags import TagsDictMixin
from botocraft.services.common import Tag
from botocraft.services.ec2 import (Instance, InstanceManager, SecurityGroup,
                                    SecurityGroupManager, Subnet,
                                    SubnetManager, Vpc, VpcManager)
from pydantic import Field

from .abstract import (Boto3Model, Boto3ModelManager, PrimaryBoto3Model,
                       ReadonlyBoto3Model, ReadonlyBoto3ModelManager,
                       ReadonlyPrimaryBoto3Model)

# ===============
# Managers
# ===============


class ClassicELBManager(ClassicELBManagerMixin, Boto3ModelManager):

    service_name: str = "elb"

    def delete(self, LoadBalancerName: str) -> None:
        """
        Deletes the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
        """
        args: Dict[str, Any] = dict(LoadBalancerName=self.serialize(LoadBalancerName))
        self.client.delete_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )

    @add_attributes_for_get
    @add_tags_for_get
    def get(self, LoadBalancerName: str) -> Optional["ClassicELB"]:
        """
        Describes the specified the load balancers. If no load balancers are specified, the call describes all of your
        load balancers.

        Args:
            LoadBalancerName: The name of the classic load balancer.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerNames=self.serialize([LoadBalancerName])
        )
        _response = self.client.describe_load_balancers(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeAccessPointsOutput(**_response)

        if response and response.LoadBalancerDescriptions:
            self.sessionize(response.LoadBalancerDescriptions[0])
            return response.LoadBalancerDescriptions[0]
        return None

    @add_attributes_for_list
    @add_tags_for_list
    def list(
        self, *, LoadBalancerNames: Optional[List[str]] = None
    ) -> List["ClassicELB"]:
        """
        Describes the specified the load balancers. If no load balancers are specified, the call describes all of your
        load balancers.

        Keyword Args:
            LoadBalancerNames: The names of the load balancers.
        """
        paginator = self.client.get_paginator("describe_load_balancers")
        args: Dict[str, Any] = dict(LoadBalancerNames=self.serialize(LoadBalancerNames))
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results: List["ClassicELB"] = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = DescribeAccessPointsOutput(**_response)
            if response.LoadBalancerDescriptions:
                results.extend(response.LoadBalancerDescriptions)
            else:
                break
        self.sessionize(results)
        return results

    def add_tags(self, LoadBalancerNames: List[str], Tags: List[Tag]) -> None:
        """
        Adds the specified tags to the specified load balancer. Each load balancer can have a maximum of 10 tags.

        Args:
            LoadBalancerNames: The name of the load balancer. You can specify one load balancer only.
            Tags: The tags.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerNames=self.serialize(LoadBalancerNames),
            Tags=self.serialize(Tags),
        )
        self.client.add_tags(**{k: v for k, v in args.items() if v is not None})

    def describe_tags(
        self, LoadBalancerNames: List[str]
    ) -> List["ClassicELBTagDescription"]:
        """
        Describes the tags associated with the specified load balancers.

        Args:
            LoadBalancerNames: The names of the load balancers.
        """
        args: Dict[str, Any] = dict(LoadBalancerNames=self.serialize(LoadBalancerNames))
        _response = self.client.describe_tags(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeTagsOutput(**_response)

        results: List["ClassicELBTagDescription"] = None
        if response is not None:
            results = response.TagDescriptions

        self.sessionize(results)
        return cast(List["ClassicELBTagDescription"], results)

    def remove_tags(
        self, LoadBalancerNames: List[str], Tags: List["TagKeyOnly"]
    ) -> None:
        """
        Removes one or more tags from the specified load balancer.

        Args:
            LoadBalancerNames: The name of the load balancer. You can specify a maximum of one load balancer name.
            Tags: The list of tag keys to remove.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerNames=self.serialize(LoadBalancerNames),
            Tags=self.serialize(Tags),
        )
        self.client.remove_tags(**{k: v for k, v in args.items() if v is not None})

    def enable_availability_zones(
        self, LoadBalancerName: str, AvailabilityZones: List[str]
    ) -> List[str]:
        """
        Adds the specified Availability Zones to the set of Availability Zones for the specified load balancer in
        EC2-Classic or a default VPC.

        Args:
            LoadBalancerName: The name of the load balancer.
            AvailabilityZones: The Availability Zones. These must be in the same region as the load balancer.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            AvailabilityZones=self.serialize(AvailabilityZones),
        )
        _response = self.client.enable_availability_zones_for_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = AddAvailabilityZonesOutput(**_response)

        results: List[str] = None
        if response is not None:
            results = response.AvailabilityZones

        self.sessionize(results)
        return cast(List[str], results)

    def disable_availability_zones(
        self, LoadBalancerName: str, AvailabilityZones: List[str]
    ) -> List[str]:
        """
        Removes the specified Availability Zones from the set of Availability Zones for the specified load balancer in
        EC2-Classic or a default VPC.

        Args:
            LoadBalancerName: The name of the load balancer.
            AvailabilityZones: The Availability Zones.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            AvailabilityZones=self.serialize(AvailabilityZones),
        )
        _response = self.client.disable_availability_zones_for_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = RemoveAvailabilityZonesOutput(**_response)

        results: List[str] = None
        if response is not None:
            results = response.AvailabilityZones

        self.sessionize(results)
        return cast(List[str], results)

    def configure_health_check(
        self, LoadBalancerName: str, HealthCheck: "ClassicELBHealthCheck"
    ) -> None:
        """
        Specifies the health check settings to use when evaluating the health state of your EC2 instances.

        Args:
            LoadBalancerName: The name of the load balancer.
            HealthCheck: The configuration information.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            HealthCheck=self.serialize(HealthCheck),
        )
        self.client.configure_health_check(
            **{k: v for k, v in args.items() if v is not None}
        )

    def register_instances(
        self, LoadBalancerName: str, Instances: List["ClassicELBInstance"]
    ) -> List["ClassicELBInstance"]:
        """
        Adds the specified instances to the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            Instances: The IDs of the instances.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Instances=self.serialize(Instances),
        )
        _response = self.client.register_instances_with_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = RegisterEndPointsOutput(**_response)

        results: List["ClassicELBInstance"] = None
        if response is not None:
            results = response.Instances

        self.sessionize(results)
        return cast(List["ClassicELBInstance"], results)

    def instance_health(
        self,
        LoadBalancerName: str,
        *,
        Instances: Optional[List["ClassicELBInstance"]] = None
    ) -> List["ClassicELBInstanceState"]:
        """
        Describes the state of the specified instances with respect to the specified load balancer. If no instances are
        specified, the call describes the state of all instances that are currently registered with the load balancer.
        If instances are specified, their state is returned even if they are no longer registered with the load
        balancer. The state of terminated instances is not returned.

        Args:
            LoadBalancerName: The name of the load balancer.

        Keyword Args:
            Instances: The IDs of the instances.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Instances=self.serialize(Instances),
        )
        _response = self.client.describe_instance_health(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeEndPointStateOutput(**_response)

        results: List["ClassicELBInstanceState"] = None
        if response is not None:
            results = response.InstanceStates

        self.sessionize(results)
        return cast(List["ClassicELBInstanceState"], results)

    def deregister_instances(
        self, LoadBalancerName: str, Instances: List["ClassicELBInstance"]
    ) -> List["ClassicELBInstance"]:
        """
        Deregisters the specified instances from the specified load balancer. After the instance is deregistered, it no
        longer receives traffic from the load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            Instances: The IDs of the instances.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Instances=self.serialize(Instances),
        )
        _response = self.client.deregister_instances_from_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DeregisterEndPointsOutput(**_response)

        results: List["ClassicELBInstance"] = None
        if response is not None:
            results = response.Instances

        self.sessionize(results)
        return cast(List["ClassicELBInstance"], results)

    def add_listeners(
        self, LoadBalancerName: str, Listeners: List["ClassicELBListener"]
    ) -> None:
        """
        Creates one or more listeners for the specified load balancer. If a listener with the specified port does not
        already exist, it is created; otherwise, the properties of the new listener must match the properties of the
        existing listener.

        Args:
            LoadBalancerName: The name of the load balancer.
            Listeners: The listeners.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Listeners=self.serialize(Listeners),
        )
        self.client.create_load_balancer_listeners(
            **{k: v for k, v in args.items() if v is not None}
        )

    def remove_listeners(
        self, LoadBalancerName: str, LoadBalancerPorts: List[int]
    ) -> None:
        """
        Deletes the specified listeners from the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            LoadBalancerPorts: The client port numbers of the listeners.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            LoadBalancerPorts=self.serialize(LoadBalancerPorts),
        )
        self.client.delete_load_balancer_listeners(
            **{k: v for k, v in args.items() if v is not None}
        )

    def describe_attributes(
        self, LoadBalancerName: str
    ) -> "ClassicELBLoadBalancerAttributes":
        """
        Describes the attributes for the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
        """
        args: Dict[str, Any] = dict(LoadBalancerName=self.serialize(LoadBalancerName))
        _response = self.client.describe_load_balancer_attributes(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeClassicELBAttributesResponse(**_response)

        results: "ClassicELBLoadBalancerAttributes" = None
        if response is not None:
            results = response.LoadBalancerAttributes

        self.sessionize(results)
        return cast("ClassicELBLoadBalancerAttributes", results)

    def modify_attributes(
        self,
        LoadBalancerName: str,
        LoadBalancerAttributes: "ClassicELBLoadBalancerAttributes",
    ) -> "ClassicELBLoadBalancerAttributes":
        """
        Modifies the attributes of the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            LoadBalancerAttributes: The attributes for the load balancer.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            LoadBalancerAttributes=self.serialize(LoadBalancerAttributes),
        )
        _response = self.client.modify_load_balancer_attributes(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = ModifyLoadBalancerAttributesOutput(**_response)

        results: "ClassicELBLoadBalancerAttributes" = None
        if response is not None:
            results = response.LoadBalancerAttributes

        self.sessionize(results)
        return cast("ClassicELBLoadBalancerAttributes", results)

    def detach_from_subnets(
        self, LoadBalancerName: str, Subnets: List[str]
    ) -> List[str]:
        """
        Removes the specified subnets from the set of configured subnets for the load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            Subnets: The IDs of the subnets.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Subnets=self.serialize(Subnets),
        )
        _response = self.client.detach_load_balancer_from_subnets(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DetachLoadBalancerFromSubnetsOutput(**_response)

        results: List[str] = None
        if response is not None:
            results = response.Subnets

        self.sessionize(results)
        return cast(List[str], results)

    def attach_to_subnets(self, LoadBalancerName: str, Subnets: List[str]) -> List[str]:
        """
        Adds one or more subnets to the set of configured subnets for the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            Subnets: The IDs of the subnets to add. You can add only one subnet per Availability Zone.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            Subnets=self.serialize(Subnets),
        )
        _response = self.client.attach_load_balancer_to_subnets(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = AttachLoadBalancerToSubnetsOutput(**_response)

        results: List[str] = None
        if response is not None:
            results = response.Subnets

        self.sessionize(results)
        return cast(List[str], results)

    def apply_security_groups(
        self, LoadBalancerName: str, SecurityGroups: List[str]
    ) -> List[str]:
        """
        Associates one or more security groups with your load balancer in a virtual private cloud (VPC). The specified
        security groups override the previously associated security groups.

        Args:
            LoadBalancerName: The name of the load balancer.
            SecurityGroups: The IDs of the security groups to associate with the load balancer. Note that you cannot specify the
                name of the security group.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            SecurityGroups=self.serialize(SecurityGroups),
        )
        _response = self.client.apply_security_groups_to_load_balancer(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = ApplySecurityGroupsToLoadBalancerOutput(**_response)

        results: List[str] = None
        if response is not None:
            results = response.SecurityGroups

        self.sessionize(results)
        return cast(List[str], results)

    def set_ssl_certificate(
        self, LoadBalancerName: str, LoadBalancerPort: int, SSLCertificateId: str
    ) -> None:
        """
        Sets the certificate that terminates the specified listener's SSL connections. The specified certificate
        replaces any prior certificate that was used on the same load balancer and port.

        Args:
            LoadBalancerName: The name of the load balancer.
            LoadBalancerPort: The port that uses the specified SSL certificate.
            SSLCertificateId: The Amazon Resource Name (ARN) of the SSL certificate.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            LoadBalancerPort=self.serialize(LoadBalancerPort),
            SSLCertificateId=self.serialize(SSLCertificateId),
        )
        self.client.set_load_balancer_listener_ssl_certificate(
            **{k: v for k, v in args.items() if v is not None}
        )

    def set_listener_policies(
        self, LoadBalancerName: str, LoadBalancerPort: int, PolicyNames: List[str]
    ) -> None:
        """
        Replaces the current set of policies for the specified load balancer port with the specified set of policies.

        Args:
            LoadBalancerName: The name of the load balancer.
            LoadBalancerPort: The external port of the load balancer.
            PolicyNames: The names of the policies. This list must include all policies to be enabled. If you omit a policy that
                is currently enabled, it is disabled. If the list is empty, all current policies are disabled.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            LoadBalancerPort=self.serialize(LoadBalancerPort),
            PolicyNames=self.serialize(PolicyNames),
        )
        self.client.set_load_balancer_policies_of_listener(
            **{k: v for k, v in args.items() if v is not None}
        )

    def set_backend_policies(
        self, LoadBalancerName: str, InstancePort: int, PolicyNames: List[str]
    ) -> None:
        """
        Replaces the set of policies associated with the specified port on which the EC2 instance is listening with a
        new set of policies. At this time, only the back-end server authentication policy type can be applied to the
        instance ports; this policy type is composed of multiple public key policies.

        Args:
            LoadBalancerName: The name of the load balancer.
            InstancePort: The port number associated with the EC2 instance.
            PolicyNames: The names of the policies. If the list is empty, then all current polices are removed from the EC2
                instance.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            InstancePort=self.serialize(InstancePort),
            PolicyNames=self.serialize(PolicyNames),
        )
        self.client.set_load_balancer_policies_for_backend_server(
            **{k: v for k, v in args.items() if v is not None}
        )

    def add_policy(
        self,
        LoadBalancerName: str,
        PolicyName: str,
        PolicyTypeName: str,
        *,
        PolicyAttributes: Optional[List["PolicyAttribute"]] = None
    ) -> None:
        """
        Creates a policy with the specified attributes for the specified load balancer.

        Args:
            LoadBalancerName: The name of the load balancer.
            PolicyName: The name of the load balancer policy to be created. This name must be unique within the set of policies
                for this load balancer.
            PolicyTypeName: The name of the base policy type. To get the list of policy types, use
                DescribeLoadBalancerPolicyTypes.

        Keyword Args:
            PolicyAttributes: The policy attributes.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            PolicyName=self.serialize(PolicyName),
            PolicyTypeName=self.serialize(PolicyTypeName),
            PolicyAttributes=self.serialize(PolicyAttributes),
        )
        self.client.create_load_balancer_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def describe_policies(
        self, LoadBalancerName: str, *, PolicyNames: Optional[List[str]] = None
    ) -> List["PolicyDescription"]:
        """
        Describes the specified policies.

        Args:
            LoadBalancerName: The name of the load balancer.

        Keyword Args:
            PolicyNames: The names of the policies.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            PolicyNames=self.serialize(PolicyNames),
        )
        _response = self.client.describe_load_balancer_policies(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeLoadBalancerPoliciesOutput(**_response)

        results: List["PolicyDescription"] = None
        if response is not None:
            results = response.PolicyDescriptions

        self.sessionize(results)
        return cast(List["PolicyDescription"], results)

    def delete_policy(self, LoadBalancerName: str, PolicyName: str) -> None:
        """
        Deletes the specified policy from the specified load balancer. This policy must not be enabled for any
        listeners.

        Args:
            LoadBalancerName: The name of the load balancer.
            PolicyName: The name of the policy.
        """
        args: Dict[str, Any] = dict(
            LoadBalancerName=self.serialize(LoadBalancerName),
            PolicyName=self.serialize(PolicyName),
        )
        self.client.delete_load_balancer_policy(
            **{k: v for k, v in args.items() if v is not None}
        )

    def describe_policy_types(
        self, PolicyTypeNames: List[str]
    ) -> List["PolicyTypeDescription"]:
        """
        Describes the specified load balancer policy types or all load balancer policy types.

        Args:
            PolicyTypeNames: The names of the policy types. If no names are specified, describes all policy types defined by
                Elastic Load Balancing.
        """
        args: Dict[str, Any] = dict(PolicyTypeNames=self.serialize(PolicyTypeNames))
        _response = self.client.describe_load_balancer_policy_types(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeLoadBalancerPolicyTypesOutput(**_response)

        results: List["PolicyTypeDescription"] = None
        if response is not None:
            results = response.PolicyTypeDescriptions

        self.sessionize(results)
        return cast(List["PolicyTypeDescription"], results)


# ==============
# Service Models
# ==============


class ClassicELBInstance(Boto3Model):
    """
    The ID of an EC2 instance.
    """

    InstanceId: Optional[str] = None
    """
    The instance ID.
    """


class ClassicELBListener(Boto3Model):
    """
    The listener.
    """

    Protocol: str
    """
The load balancer transport protocol to use for routing: HTTP, HTTPS, TCP, or SSL.
    """
    LoadBalancerPort: int
    """
    The port on which the load balancer is listening.

    On EC2-VPC, you can specify any port from the range 1-65535. On EC2-Classic, you can specify any port from the
    following list: 25, 80, 443, 465, 587, 1024-65535.
    """
    InstanceProtocol: Optional[str] = None
    """
The protocol to use for routing traffic to instances: HTTP, HTTPS, TCP, or SSL.
    """
    InstancePort: int
    """
    The port on which the instance is listening.
    """
    SSLCertificateId: Optional[str] = None
    """
    The Amazon Resource Name (ARN) of the server certificate.
    """


class ListenerDescription(Boto3Model):
    """
    The policies enabled for a listener.
    """

    Listener: Optional[ClassicELBListener] = None
    """
    The listener.
    """
    PolicyNames: Optional[List[str]] = None
    """
    The policies.

    If there are no policies enabled, the list is empty.
    """


class ClassicELBSourceSecurityGroup(Boto3Model):
    """
    The security group for the load balancer, which you can use as part of your inbound rules for your registered
    instances.

    To only allow traffic from load balancers, add a security group rule that specifies this source security group as
    the inbound source.
    """

    OwnerAlias: Optional[str] = None
    """
    The owner of the security group.
    """
    GroupName: Optional[str] = None
    """
    The name of the security group.
    """


class AppCookieStickinessPolicy(Boto3Model):
    """
    Information about a policy for application-controlled session stickiness.
    """

    PolicyName: Optional[str] = None
    """
    The mnemonic name for the policy being created.

    The name must be unique within a set of policies for this load balancer.
    """
    CookieName: Optional[str] = None
    """
    The name of the application cookie used for stickiness.
    """


class LBCookieStickinessPolicy(Boto3Model):
    """
    Information about a policy for duration-based session stickiness.
    """

    PolicyName: Optional[str] = None
    """
    The name of the policy.

    This name must be unique within the set of policies for this load balancer.
    """
    CookieExpirationPeriod: Optional[int] = None
    """
    The time period, in seconds, after which the cookie should be considered stale.

    If this parameter is not specified, the stickiness session lasts for the duration of the browser session.
    """


class ClassicELBPolicies(Boto3Model):
    """
    The policies defined for the load balancer.
    """

    AppCookieStickinessPolicies: Optional[List["AppCookieStickinessPolicy"]] = None
    """
    The stickiness policies created using CreateAppCookieStickinessPolicy.
    """
    LBCookieStickinessPolicies: Optional[List["LBCookieStickinessPolicy"]] = None
    """
    The stickiness policies created using CreateLBCookieStickinessPolicy.
    """
    OtherPolicies: Optional[List[str]] = None
    """
    The policies other than the stickiness policies.
    """


class BackendServerDescription(Boto3Model):
    """
    Information about the configuration of an EC2 instance.
    """

    InstancePort: Optional[int] = None
    """
    The port on which the EC2 instance is listening.
    """
    PolicyNames: Optional[List[str]] = None
    """
    The names of the policies enabled for the EC2 instance.
    """


class ClassicELBHealthCheck(Boto3Model):
    """
    Information about the health checks conducted on the load balancer.
    """

    Target: str
    """
    The instance being checked.

    The protocol is either TCP, HTTP, HTTPS, or SSL. The range of valid ports is one (1) through 65535.
    """
    Interval: int
    """
    The approximate interval, in seconds, between health checks of an individual instance.
    """
    Timeout: int
    """
    The amount of time, in seconds, during which no response means a failed health check.
    """
    UnhealthyThreshold: int
    """
    The number of consecutive health check failures required before moving the instance to the ``Unhealthy`` state.
    """
    HealthyThreshold: int
    """
    The number of consecutive health checks successes required before moving the instance to the ``Healthy`` state.
    """


class PolicyAttribute(Boto3Model):
    """
    Information about a policy attribute.
    """

    AttributeName: Optional[str] = None
    """
    The name of the attribute.
    """
    AttributeValue: Optional[str] = None
    """
    The value of the attribute.
    """


class ClassicELB(TagsDictMixin, ClassicELBModelMixin, PrimaryBoto3Model):
    """
    Information about a load balancer.
    """

    tag_class: ClassVar[Type] = Dict[str, str]
    manager_class: ClassVar[Type[Boto3ModelManager]] = ClassicELBManager

    LoadBalancerName: str
    """
    The name of the load balancer.
    """
    AvailabilityZones: List[str]
    """
    The Availability Zones for the load balancer.
    """
    Scheme: Optional[str] = ""
    """
    The type of load balancer.

    Valid only for load balancers in a VPC.
    """
    VPCId: str = Field(default=None, frozen=True)
    """
    The ID of the VPC for the load balancer.
    """
    CreatedTime: datetime = Field(default=None, frozen=True)
    """
    The date and time the load balancer was created.
    """
    Instances: List["ClassicELBInstance"] = Field(default=None, frozen=True)
    """
    The IDs of the instances for the load balancer.
    """
    DNSName: str = Field(default=None, frozen=True)
    """
    The DNS name of the load balancer.
    """
    CanonicalHostedZoneName: str = Field(default=None, frozen=True)
    """
    The DNS name of the load balancer.
    """
    CanonicalHostedZoneNameID: str = Field(default=None, frozen=True)
    """
    The ID of the Amazon Route 53 hosted zone for the load balancer.
    """
    Listeners: List["ListenerDescription"] = Field(
        default=None, serialization_alias="ListenerDescriptions", frozen=True
    )
    """
    The listeners for the load balancer.
    """
    SourceSecurityGroup: ClassicELBSourceSecurityGroup = Field(
        default=None, frozen=True
    )
    """
    The security group for the load balancer, which you can use as part of your inbound rules for your registered
    instances.

    To only allow traffic from load balancers, add a security group rule that specifies this source security group as
    the inbound source.
    """
    Policies: Optional[ClassicELBPolicies] = None
    """
    The policies defined for the load balancer.
    """
    BackendServerDescriptions: Optional[List["BackendServerDescription"]] = None
    """
    Information about your EC2 instances.
    """
    Subnets: Optional[List[str]] = None
    """
    The IDs of the subnets for the load balancer.
    """
    HealthCheck: Optional[ClassicELBHealthCheck] = None
    """
    Information about the health checks conducted on the load balancer.
    """
    SecurityGroups: Optional[List[str]] = None
    """
    The security groups for the load balancer.

    Valid only for load balancers in a VPC.
    """
    Tags: Optional[Dict[str, str]] = None
    """
    The tags associated with the load balancer.
    """
    CrossZoneLoadBalancing: Optional[bool] = False
    """
    Whether cross-zone load balancing is enabled for the load balancer.
    """
    AccessLog: Optional["ClassicELBAccessLog"] = None
    """
    The access log settings for the load balancer.
    """
    ConnectionDraining: Optional["ClassicELBConnectionDraining"] = None
    """
    The connection draining settings for the load balancer.
    """
    ConnectionSettings: Optional["ClassicELBConnectionSettings"] = None
    """
    The connection settings for the load balancer.
    """
    AdditionalAttributes: Optional[Dict[str, str]] = None
    """
    Additional attributes for the load balancer.
    """

    @property
    def pk(self) -> Optional[str]:
        """
        Return the primary key of the model.   This is the value of the :py:attr:`LoadBalancerName` attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.LoadBalancerName

    @property
    def name(self) -> Optional[str]:
        """
        Return the name of the model.   This is the value of the :py:attr:`LoadBalancerName` attribute.

        Returns:
            The name of the model instance.
        """
        return self.LoadBalancerName

    @cached_property
    def vpc(self) -> Optional["Vpc"]:
        """
        Return the :py:class:`Vpc` object that this load balancer is associated with.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "VpcId": self.VPCId,
                }
            )
        except AttributeError:
            return None
        return Vpc.objects.using(self.session).get(**pk)  # type: ignore[arg-type]

    @cached_property
    def security_groups(self) -> Optional[List["SecurityGroup"]]:
        """
        Return the security groups associated with this load balancer.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "GroupIds": self.SecurityGroups,
                }
            )
        except AttributeError:
            return []
        return SecurityGroup.objects.using(self.session).list(**pk)  # type: ignore[arg-type]

    @cached_property
    def subnets(self) -> Optional[List["Subnet"]]:
        """
        Return the subnets associated with this load balancer.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "SubnetIds": self.Subnets,
                }
            )
        except AttributeError:
            return []
        return Subnet.objects.using(self.session).list(**pk)  # type: ignore[arg-type]

    @cached_property
    def instances(self) -> Optional[List["Instance"]]:
        """
        Return the instances associated with this load balancer.

        .. note::

            The output of this property is cached on the model instance, so
            calling this multiple times will not result in multiple calls to the
            AWS API.   If you need a fresh copy of the data, you can re-get the
            model instance from the manager.
        """

        try:
            pk = OrderedDict(
                {
                    "InstanceIds": [instance.InstanceId for instance in self.Instances],
                }
            )
        except AttributeError:
            return []
        return Instance.objects.using(self.session).list(**pk)  # type: ignore[arg-type]

    def add_listeners(self, Listeners: List["ClassicELBListener"]) -> "None":
        """
        Add listeners to the load balancer.

        Args:
            Listeners: The listeners.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .add_listeners(
                cast(str, self.LoadBalancerName),
                Listeners,
            )
        )

    def remove_listeners(self, LoadBalancerPorts: List[int]) -> "None":
        """
        Remove listeners from the load balancer.

        Args:
            LoadBalancerPorts: The client port numbers of the listeners.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .remove_listeners(
                cast(str, self.LoadBalancerName),
                LoadBalancerPorts,
            )
        )

    def set_ssl_certificate(
        self, LoadBalancerPort: int, SSLCertificateId: str
    ) -> "None":
        """
        Set the SSL certificate for a listener on the load balancer.

        Args:
            LoadBalancerPort: The port that uses the specified SSL certificate.
            SSLCertificateId: The Amazon Resource Name (ARN) of the SSL certificate.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .set_ssl_certificate(
                cast(str, self.LoadBalancerName),
                LoadBalancerPort,
                SSLCertificateId,
            )
        )

    def set_listener_policies(
        self, LoadBalancerPort: int, PolicyNames: List[str]
    ) -> "None":
        """
        Set the policies for a listener on the load balancer.

        Args:
            LoadBalancerPort: The external port of the load balancer.
            PolicyNames: The names of the policies. This list must include all policies to be enabled. If you omit a policy that
                is currently enabled, it is disabled. If the list is empty, all current policies are disabled.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .set_listener_policies(
                cast(str, self.LoadBalancerName),
                LoadBalancerPort,
                PolicyNames,
            )
        )

    def set_backend_policies(self, InstancePort: int, PolicyNames: List[str]) -> "None":
        """
        Set the policies for a backend server on the load balancer.

        Args:
            InstancePort: The port number associated with the EC2 instance.
            PolicyNames: The names of the policies. If the list is empty, then all current polices are removed from the EC2
                instance.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .set_backend_policies(
                cast(str, self.LoadBalancerName),
                InstancePort,
                PolicyNames,
            )
        )

    def add_policy(
        self,
        PolicyName: str,
        PolicyTypeName: str,
        PolicyAttributes: Optional[List["PolicyAttribute"]] = None,
    ) -> "None":
        """
        Add a policy to the load balancer.

        Args:
            PolicyName: The name of the load balancer policy to be created. This name must be unique within the set of policies
                for this load balancer.
            PolicyTypeName: The name of the base policy type. To get the list of policy types, use
                DescribeLoadBalancerPolicyTypes.

        Keyword Args:
            PolicyAttributes: The policy attributes.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .add_policy(
                cast(str, self.LoadBalancerName),
                PolicyName,
                PolicyTypeName,
                PolicyAttributes=PolicyAttributes,
            )
        )

    def policies(self) -> "DescribeLoadBalancerPoliciesOutput":
        """
        Return the policies associated with this load balancer.

        This is excludes the StickinessPolicy and the LBCookieStickinessPolicy. You can look directly on this object for
        those policies.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .describe_policies()
        )

    def delete_policy(self, PolicyName: str) -> "None":
        """
        Delete a policy from the load balancer.

        Args:
            PolicyName: The name of the policy.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .delete_policy(
                cast(str, self.LoadBalancerName),
                PolicyName,
            )
        )

    def add_instances(
        self, Instances: List["ClassicELBInstance"]
    ) -> "RegisterEndPointsOutput":
        """
        Add instances to the load balancer.

        Args:
            Instances: The IDs of the instances.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .register_instances(
                cast(str, self.LoadBalancerName),
                Instances,
            )
        )

    def remove_instances(
        self, Instances: List["ClassicELBInstance"]
    ) -> "DeregisterEndPointsOutput":
        """
        Remove instances from the load balancer.

        Args:
            Instances: The IDs of the instances.
        """

        return (
            cast(ClassicELBManager, self.objects)
            .using(self.session)
            .deregister_instances(
                cast(str, self.LoadBalancerName),
                Instances,
            )
        )


# =======================
# Request/Response Models
# =======================


class DeleteAccessPointOutput(Boto3Model):
    """
    Contains the output of DeleteLoadBalancer.
    """

    pass


class DescribeAccessPointsOutput(Boto3Model):
    """
    Contains the parameters for DescribeLoadBalancers.
    """

    LoadBalancerDescriptions: Optional[List["ClassicELB"]] = None
    """
    Information about the load balancers.
    """
    NextMarker: Optional[str] = None
    """
    The marker to use when requesting the next set of results.

    If there are no additional results, the string is empty.
    """


class AddTagsOutput(Boto3Model):
    """
    Contains the output of AddTags.
    """

    pass


class ClassicELBTagDescription(TagsDictMixin, Boto3Model):
    """
    The tags associated with a load balancer.
    """

    tag_class: ClassVar[Type] = Tag
    LoadBalancerName: Optional[str] = None
    """
    The name of the load balancer.
    """
    Tags: Optional[List[Tag]] = None
    """
    The tags.
    """


class DescribeTagsOutput(Boto3Model):
    """
    Contains the output for DescribeTags.
    """

    TagDescriptions: Optional[List["ClassicELBTagDescription"]] = None
    """
    Information about the tags.
    """


class TagKeyOnly(Boto3Model):
    """
    The key of a tag.
    """

    Key: Optional[str] = None
    """
    The name of the key.
    """


class RemoveTagsOutput(Boto3Model):
    """
    Contains the output of RemoveTags.
    """

    pass


class AddAvailabilityZonesOutput(Boto3Model):
    """
    Contains the output of EnableAvailabilityZonesForLoadBalancer.
    """

    AvailabilityZones: Optional[List[str]] = None
    """
    The updated list of Availability Zones for the load balancer.
    """


class RemoveAvailabilityZonesOutput(Boto3Model):
    """
    Contains the output for DisableAvailabilityZonesForLoadBalancer.
    """

    AvailabilityZones: Optional[List[str]] = None
    """
    The remaining Availability Zones for the load balancer.
    """


class ConfigureHealthCheckOutput(Boto3Model):
    """
    Contains the output of ConfigureHealthCheck.
    """

    HealthCheck: Optional[ClassicELBHealthCheck] = None
    """
    The updated health check.
    """


class RegisterEndPointsOutput(Boto3Model):
    """
    Contains the output of RegisterInstancesWithLoadBalancer.
    """

    Instances: Optional[List["ClassicELBInstance"]] = None
    """
    The updated list of instances for the load balancer.
    """


class ClassicELBInstanceState(Boto3Model):
    """
    Information about the state of an EC2 instance.
    """

    InstanceId: Optional[str] = None
    """
    The ID of the instance.
    """
    State: Optional[str] = None
    """
    The current state of the instance.
    """
    ReasonCode: Optional[str] = None
    """
    Information about the cause of ``OutOfService`` instances.

    Specifically, whether the cause is Elastic Load Balancing or the instance.
    """
    Description: Optional[str] = None
    """
    A description of the instance state.

    This string can contain one or more of the following messages.
    """


class DescribeEndPointStateOutput(Boto3Model):
    """
    Contains the output for DescribeInstanceHealth.
    """

    InstanceStates: Optional[List["ClassicELBInstanceState"]] = None
    """
    Information about the health of the instances.
    """


class DeregisterEndPointsOutput(Boto3Model):
    """
    Contains the output of DeregisterInstancesFromLoadBalancer.
    """

    Instances: Optional[List["ClassicELBInstance"]] = None
    """
    The remaining instances registered with the load balancer.
    """


class CreateLoadBalancerListenerOutput(Boto3Model):
    """
    Contains the parameters for CreateLoadBalancerListener.
    """

    pass


class DeleteLoadBalancerListenerOutput(Boto3Model):
    """
    Contains the output of DeleteLoadBalancerListeners.
    """

    pass


class ClassicELBCrossZoneLoadBalancing(Boto3Model):
    """
    If enabled, the load balancer routes the request traffic evenly across all instances regardless of the Availability
    Zones.

    For more information, see `Configure Cross-Zone Load
    Balancing <https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-disable-crosszone-lb.html>`_ in the
    *Classic Load Balancers Guide*.
    """

    Enabled: bool
    """
    Specifies whether cross-zone load balancing is enabled for the load balancer.
    """


class ClassicELBAccessLog(Boto3Model):
    """
    If enabled, the load balancer captures detailed information of all requests and delivers the information to the
    Amazon S3 bucket that you specify.

    For more information, see
    `Enable Access Logs <https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-
    access-logs.html>`_ in the *Classic Load Balancers Guide*.
    """

    Enabled: bool
    """
    Specifies whether access logs are enabled for the load balancer.
    """
    S3BucketName: Optional[str] = None
    """
    The name of the Amazon S3 bucket where the access logs are stored.
    """
    EmitInterval: Optional[int] = None
    """
    The interval for publishing the access logs.

    You can specify an interval of either 5 minutes or 60 minutes.
    """
    S3BucketPrefix: Optional[str] = None
    """
    The logical hierarchy you created for your Amazon S3 bucket, for example ``my-bucket-prefix/prod``.

    If the prefix is not provided, the log is placed at the root level of the bucket.
    """


class ClassicELBConnectionDraining(Boto3Model):
    """
    If enabled, the load balancer allows existing requests to complete before the load balancer shifts traffic away from
    a deregistered or unhealthy instance.

    For more information, see
    `Configure Connection Draining <https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-conn-drain.html>`_
    in the *Classic Load
    Balancers Guide*.
    """

    Enabled: bool
    """
    Specifies whether connection draining is enabled for the load balancer.
    """
    Timeout: Optional[int] = None
    """
    The maximum time, in seconds, to keep the existing connections open before deregistering the instances.
    """


class ClassicELBConnectionSettings(Boto3Model):
    """
    If enabled, the load balancer allows the connections to remain idle (no data is sent over the connection) for the
    specified duration.

    By default, Elastic Load Balancing maintains a 60-second idle connection timeout for both front-end and back-end
    connections of your load balancer. For more information, see
    `Configure Idle Connection Timeout <https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-idle-timeout.html>`_
    in the *Classic Load
    Balancers Guide*.
    """

    IdleTimeout: int
    """
    The time, in seconds, that the connection is allowed to be idle (no data has been sent over the connection) before
    it is closed by the load balancer.
    """


class AdditionalAttribute(Boto3Model):
    """
    Information about additional load balancer attributes.
    """

    Key: Optional[str] = None
    """
    The name of the attribute.
    """
    Value: Optional[str] = None
    """
    This value of the attribute.
    """


class ClassicELBLoadBalancerAttributes(Boto3Model):
    """
    Information about the load balancer attributes.
    """

    CrossZoneLoadBalancing: Optional[ClassicELBCrossZoneLoadBalancing] = None
    """
    If enabled, the load balancer routes the request traffic evenly across all instances regardless of the Availability
    Zones.
    """
    AccessLog: Optional[ClassicELBAccessLog] = None
    """
    If enabled, the load balancer captures detailed information of all requests and delivers the information to the
    Amazon S3 bucket that you specify.
    """
    ConnectionDraining: Optional[ClassicELBConnectionDraining] = None
    """
    If enabled, the load balancer allows existing requests to complete before the load balancer shifts traffic away from
    a deregistered or unhealthy instance.
    """
    ConnectionSettings: Optional[ClassicELBConnectionSettings] = None
    """
    If enabled, the load balancer allows the connections to remain idle (no data is sent over the connection) for the
    specified duration.
    """
    AdditionalAttributes: Optional[List["AdditionalAttribute"]] = None
    """
    Any additional attributes.
    """


class DescribeClassicELBAttributesResponse(Boto3Model):
    """
    Contains the output of DescribeLoadBalancerAttributes.
    """

    LoadBalancerAttributes: Optional[ClassicELBLoadBalancerAttributes] = None
    """
    Information about the load balancer attributes.
    """


class ModifyLoadBalancerAttributesOutput(Boto3Model):
    """
    Contains the output of ModifyLoadBalancerAttributes.
    """

    LoadBalancerName: Optional[str] = None
    """
    The name of the load balancer.
    """
    LoadBalancerAttributes: Optional[ClassicELBLoadBalancerAttributes] = None
    """
    Information about the load balancer attributes.
    """


class DetachLoadBalancerFromSubnetsOutput(Boto3Model):
    """
    Contains the output of DetachLoadBalancerFromSubnets.
    """

    Subnets: Optional[List[str]] = None
    """
    The IDs of the remaining subnets for the load balancer.
    """


class AttachLoadBalancerToSubnetsOutput(Boto3Model):
    """
    Contains the output of AttachLoadBalancerToSubnets.
    """

    Subnets: Optional[List[str]] = None
    """
    The IDs of the subnets attached to the load balancer.
    """


class ApplySecurityGroupsToLoadBalancerOutput(Boto3Model):
    """
    Contains the output of ApplySecurityGroupsToLoadBalancer.
    """

    SecurityGroups: Optional[List[str]] = None
    """
    The IDs of the security groups associated with the load balancer.
    """


class SetLoadBalancerListenerSSLCertificateOutput(Boto3Model):
    """
    Contains the output of SetLoadBalancerListenerSSLCertificate.
    """

    pass


class SetLoadBalancerPoliciesOfListenerOutput(Boto3Model):
    """
    Contains the output of SetLoadBalancePoliciesOfListener.
    """

    pass


class SetLoadBalancerPoliciesForBackendServerOutput(Boto3Model):
    """
    Contains the output of SetLoadBalancerPoliciesForBackendServer.
    """

    pass


class CreateLoadBalancerPolicyOutput(Boto3Model):
    """
    Contains the output of CreateLoadBalancerPolicy.
    """

    pass


class PolicyAttributeDescription(Boto3Model):
    """
    Information about a policy attribute.
    """

    AttributeName: Optional[str] = None
    """
    The name of the attribute.
    """
    AttributeValue: Optional[str] = None
    """
    The value of the attribute.
    """


class PolicyDescription(Boto3Model):
    """
    Information about a policy.
    """

    PolicyName: Optional[str] = None
    """
    The name of the policy.
    """
    PolicyTypeName: Optional[str] = None
    """
    The name of the policy type.
    """
    PolicyAttributeDescriptions: Optional[List["PolicyAttributeDescription"]] = None
    """
    The policy attributes.
    """


class DescribeLoadBalancerPoliciesOutput(Boto3Model):
    """
    Contains the output of DescribeLoadBalancerPolicies.
    """

    PolicyDescriptions: Optional[List["PolicyDescription"]] = None
    """
    Information about the policies.
    """


class DeleteLoadBalancerPolicyOutput(Boto3Model):
    """
    Contains the output of DeleteLoadBalancerPolicy.
    """

    pass


class PolicyAttributeTypeDescription(Boto3Model):
    """
    Information about a policy attribute type.
    """

    AttributeName: Optional[str] = None
    """
    The name of the attribute.
    """
    AttributeType: Optional[str] = None
    """
    The type of the attribute.

    For example, ``Boolean`` or ``Integer``.
    """
    Description: Optional[str] = None
    """
    A description of the attribute.
    """
    DefaultValue: Optional[str] = None
    """
    The default value of the attribute, if applicable.
    """
    Cardinality: Optional[str] = None
    """
    The cardinality of the attribute.
    """


class PolicyTypeDescription(Boto3Model):
    """
    Information about a policy type.
    """

    PolicyTypeName: Optional[str] = None
    """
    The name of the policy type.
    """
    Description: Optional[str] = None
    """
    A description of the policy type.
    """
    PolicyAttributeTypeDescriptions: Optional[
        List["PolicyAttributeTypeDescription"]
    ] = None
    """
    The description of the policy attributes associated with the policies defined by Elastic Load Balancing.
    """


class DescribeLoadBalancerPolicyTypesOutput(Boto3Model):
    """
    Contains the output of DescribeLoadBalancerPolicyTypes.
    """

    PolicyTypeDescriptions: Optional[List["PolicyTypeDescription"]] = None
    """
    Information about the policy types.
    """
