# This file is automatically generated by botocraft.  Do not edit directly.
# mypy: disable-error-code="index, override, assignment, union-attr, misc"
from botocraft.mixins.elb import add_attributes_for_list
from botocraft.mixins.tags import TagsDictMixin
from collections import OrderedDict
from typing import ClassVar, Type, Optional, Literal, Dict, List, Union, Any, cast
from botocraft.mixins.elb import ClassicELBModelMixin
from datetime import datetime
from botocraft.services.common import Tag
from pydantic import Field
from botocraft.services.ec2 import SecurityGroup, SecurityGroupManager
from botocraft.mixins.elb import add_tags_for_get
from .abstract import PrimaryBoto3ModelQuerySet
from botocraft.services.ec2 import Vpc, VpcManager
from botocraft.services.ec2 import Subnet, SubnetManager
from botocraft.services.ec2 import Instance, InstanceManager
from botocraft.mixins.elb import ClassicELBManagerMixin
from botocraft.mixins.elb import add_attributes_for_get
from .abstract import (
    Boto3Model,
    ReadonlyBoto3Model,
    PrimaryBoto3Model,
    ReadonlyPrimaryBoto3Model,
    Boto3ModelManager,
    ReadonlyBoto3ModelManager,
)
from functools import cached_property
from botocraft.mixins.elb import add_tags_for_list

# ===============
# 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: List[str] | None = None
    ) -> PrimaryBoto3ModelQuerySet:
        """
        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 = []
        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:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(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: List["ClassicELBInstance"] | None = 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: List["PolicyAttribute"] | None = 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: List[str] | None = 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: str | None = None
    """
    The instance ID.
    """


class ClassicELBListener(Boto3Model):
    """
    Information about a listener.

    For information about the protocols and the ports supported by Elastic Load
    Balancing, see
    `Listeners for Your Classic Load Balancer <https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html>`_
    in the *Classic
    Load Balancers Guide*.
    """

    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: str | None = 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: str | None = None
    """
    The Amazon Resource Name (ARN) of the server certificate.
    """


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

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

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


class ClassicELBSourceSecurityGroup(Boto3Model):
    """
    Information about a source security group.
    """

    OwnerAlias: str | None = None
    """
    The owner of the security group.
    """
    GroupName: str | None = None
    """
    The name of the security group.
    """


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

    PolicyName: str | None = None
    """
    The mnemonic name for the policy being created.

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


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

    PolicyName: str | None = None
    """
    The name of the policy.

    This name must be unique within the set of policies for this load balancer.
    """
    CookieExpirationPeriod: int | None = 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 for a load balancer.
    """

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


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

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


class ClassicELBHealthCheck(Boto3Model):
    """
    Information about a health check.
    """

    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: str | None = None
    """
    The name of the attribute.
    """
    AttributeValue: str | None = None
    """
    The value of the attribute.
    """


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

    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: str | None = ""
    """
    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_factory=list, 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_factory=list, 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: ClassicELBPolicies | None = None
    """
    The policies defined for the load balancer.
    """
    BackendServerDescriptions: List["BackendServerDescription"] | None = None
    """
    Information about your EC2 instances.
    """
    Subnets: List[str] | None = None
    """
    The IDs of the subnets for the load balancer.
    """
    HealthCheck: ClassicELBHealthCheck | None = None
    """
    Information about the health checks conducted on the load balancer.
    """
    SecurityGroups: List[str] | None = None
    """
    The security groups for the load balancer.

    Valid only for load balancers in a VPC.
    """
    Tags: Dict[str, str] | None = None
    """
    The tags associated with the load balancer.
    """
    CrossZoneLoadBalancing: bool | None = 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: Dict[str, str] | None = None
    """
    Additional attributes for the load balancer.
    """

    @property
    def pk(self) -> str | None:
        """
        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) -> str | None:
        """
        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

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`LoadBalancerName` attribute.
        """
        return hash(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) -> List["SecurityGroup"] | None:
        """
        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) -> List["Subnet"] | None:
        """
        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) -> List["Instance"] | None:
        """
        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)  # type: ignore[attr-defined]
            .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)  # type: ignore[attr-defined]
            .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)  # type: ignore[attr-defined]
            .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)  # type: ignore[attr-defined]
            .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)  # type: ignore[attr-defined]
            .using(self.session)
            .set_backend_policies(
                cast("str", self.LoadBalancerName),
                InstancePort,
                PolicyNames,
            )
        )

    def add_policy(
        self,
        PolicyName: str,
        PolicyTypeName: str,
        PolicyAttributes: List["PolicyAttribute"] | None = 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)  # type: ignore[attr-defined]
            .using(self.session)
            .add_policy(
                cast("str", self.LoadBalancerName),
                PolicyName,
                PolicyTypeName,
                PolicyAttributes=PolicyAttributes,
            )
        )

    def policies(self) -> List["PolicyDescription"]:
        """
        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)  # type: ignore[attr-defined]
            .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)  # type: ignore[attr-defined]
            .using(self.session)
            .delete_policy(
                cast("str", self.LoadBalancerName),
                PolicyName,
            )
        )

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

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

        return (
            cast("ClassicELBManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .register_instances(
                cast("str", self.LoadBalancerName),
                Instances,
            )
        )

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

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

        return (
            cast("ClassicELBManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .deregister_instances(
                cast("str", self.LoadBalancerName),
                Instances,
            )
        )


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


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



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

    LoadBalancerDescriptions: List["ClassicELB"] | None = None
    """
    Information about the load balancers.
    """
    NextMarker: str | None = 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.
    """



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

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


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

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


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

    Key: str | None = None
    """
    The name of the key.
    """


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



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

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


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

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


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

    HealthCheck: ClassicELBHealthCheck | None = None
    """
    The updated health check.
    """


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

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


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

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

    Specifically, whether the cause is Elastic Load Balancing or the instance.
    """
    Description: str | None = 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: List["ClassicELBInstanceState"] | None = None
    """
    Information about the health of the instances.
    """


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

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


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



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



class ClassicELBCrossZoneLoadBalancing(Boto3Model):
    """
    Information about the ``CrossZoneLoadBalancing`` attribute.
    """

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


class ClassicELBAccessLog(Boto3Model):
    """
    Information about the ``AccessLog`` attribute.
    """

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

    You can specify an interval of either 5 minutes or 60 minutes.
    """
    S3BucketPrefix: str | None = 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):
    """
    Information about the ``ConnectionDraining`` attribute.
    """

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


class ClassicELBConnectionSettings(Boto3Model):
    """
    Information about the ``ConnectionSettings`` attribute.
    """

    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: str | None = None
    """
    The name of the attribute.
    """
    Value: str | None = None
    """
    This value of the attribute.
    """


class ClassicELBLoadBalancerAttributes(Boto3Model):
    """
    The attributes for a load balancer.
    """

    CrossZoneLoadBalancing: ClassicELBCrossZoneLoadBalancing | None = None
    """
    If enabled, the load balancer routes the request traffic evenly across all instances
    regardless of the Availability Zones.
    """
    AccessLog: ClassicELBAccessLog | None = 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: ClassicELBConnectionDraining | None = 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: ClassicELBConnectionSettings | None = None
    """
    If enabled, the load balancer allows the connections to remain idle (no data is sent
    over the connection) for the specified duration.
    """
    AdditionalAttributes: List["AdditionalAttribute"] | None = None
    """
    Any additional attributes.
    """


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

    LoadBalancerAttributes: ClassicELBLoadBalancerAttributes | None = None
    """
    Information about the load balancer attributes.
    """


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

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


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

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


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

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


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

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


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



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



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



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



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

    AttributeName: str | None = None
    """
    The name of the attribute.
    """
    AttributeValue: str | None = None
    """
    The value of the attribute.
    """


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

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


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

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


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



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

    AttributeName: str | None = None
    """
    The name of the attribute.
    """
    AttributeType: str | None = None
    """
    The type of the attribute.

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


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

    PolicyTypeName: str | None = None
    """
    The name of the policy type.
    """
    Description: str | None = None
    """
    A description of the policy type.
    """
    PolicyAttributeTypeDescriptions: List["PolicyAttributeTypeDescription"] | None = 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: List["PolicyTypeDescription"] | None = None
    """
    Information about the policy types.
    """
