from __future__ import annotations

import enum
from typing import List

from mypy_boto3_builder.constants import PYPI_NAME, MODULE_NAME, WITH_DOCS_PYPI_POSTFIX


class ServiceName(enum.Enum):
    acm = "acm"
    acm_with_docs = "acm-with-docs"
    acm_pca = "acm-pca"
    acm_pca_with_docs = "acm-pca-with-docs"
    alexaforbusiness = "alexaforbusiness"
    alexaforbusiness_with_docs = "alexaforbusiness-with-docs"
    amplify = "amplify"
    amplify_with_docs = "amplify-with-docs"
    apigateway = "apigateway"
    apigateway_with_docs = "apigateway-with-docs"
    apigatewaymanagementapi = "apigatewaymanagementapi"
    apigatewaymanagementapi_with_docs = "apigatewaymanagementapi-with-docs"
    apigatewayv2 = "apigatewayv2"
    apigatewayv2_with_docs = "apigatewayv2-with-docs"
    application_autoscaling = "application-autoscaling"
    application_autoscaling_with_docs = "application-autoscaling-with-docs"
    application_insights = "application-insights"
    application_insights_with_docs = "application-insights-with-docs"
    appmesh = "appmesh"
    appmesh_with_docs = "appmesh-with-docs"
    appstream = "appstream"
    appstream_with_docs = "appstream-with-docs"
    appsync = "appsync"
    appsync_with_docs = "appsync-with-docs"
    athena = "athena"
    athena_with_docs = "athena-with-docs"
    autoscaling = "autoscaling"
    autoscaling_with_docs = "autoscaling-with-docs"
    autoscaling_plans = "autoscaling-plans"
    autoscaling_plans_with_docs = "autoscaling-plans-with-docs"
    backup = "backup"
    backup_with_docs = "backup-with-docs"
    batch = "batch"
    batch_with_docs = "batch-with-docs"
    budgets = "budgets"
    budgets_with_docs = "budgets-with-docs"
    ce = "ce"
    ce_with_docs = "ce-with-docs"
    chime = "chime"
    chime_with_docs = "chime-with-docs"
    cloud9 = "cloud9"
    cloud9_with_docs = "cloud9-with-docs"
    clouddirectory = "clouddirectory"
    clouddirectory_with_docs = "clouddirectory-with-docs"
    cloudformation = "cloudformation"
    cloudformation_with_docs = "cloudformation-with-docs"
    cloudfront = "cloudfront"
    cloudfront_with_docs = "cloudfront-with-docs"
    cloudhsm = "cloudhsm"
    cloudhsm_with_docs = "cloudhsm-with-docs"
    cloudhsmv2 = "cloudhsmv2"
    cloudhsmv2_with_docs = "cloudhsmv2-with-docs"
    cloudsearch = "cloudsearch"
    cloudsearch_with_docs = "cloudsearch-with-docs"
    cloudsearchdomain = "cloudsearchdomain"
    cloudsearchdomain_with_docs = "cloudsearchdomain-with-docs"
    cloudtrail = "cloudtrail"
    cloudtrail_with_docs = "cloudtrail-with-docs"
    cloudwatch = "cloudwatch"
    cloudwatch_with_docs = "cloudwatch-with-docs"
    codebuild = "codebuild"
    codebuild_with_docs = "codebuild-with-docs"
    codecommit = "codecommit"
    codecommit_with_docs = "codecommit-with-docs"
    codedeploy = "codedeploy"
    codedeploy_with_docs = "codedeploy-with-docs"
    codepipeline = "codepipeline"
    codepipeline_with_docs = "codepipeline-with-docs"
    codestar = "codestar"
    codestar_with_docs = "codestar-with-docs"
    codestar_notifications = "codestar-notifications"
    codestar_notifications_with_docs = "codestar-notifications-with-docs"
    cognito_identity = "cognito-identity"
    cognito_identity_with_docs = "cognito-identity-with-docs"
    cognito_idp = "cognito-idp"
    cognito_idp_with_docs = "cognito-idp-with-docs"
    cognito_sync = "cognito-sync"
    cognito_sync_with_docs = "cognito-sync-with-docs"
    comprehend = "comprehend"
    comprehend_with_docs = "comprehend-with-docs"
    comprehendmedical = "comprehendmedical"
    comprehendmedical_with_docs = "comprehendmedical-with-docs"
    config = "config"
    config_with_docs = "config-with-docs"
    connect = "connect"
    connect_with_docs = "connect-with-docs"
    cur = "cur"
    cur_with_docs = "cur-with-docs"
    datapipeline = "datapipeline"
    datapipeline_with_docs = "datapipeline-with-docs"
    datasync = "datasync"
    datasync_with_docs = "datasync-with-docs"
    dax = "dax"
    dax_with_docs = "dax-with-docs"
    devicefarm = "devicefarm"
    devicefarm_with_docs = "devicefarm-with-docs"
    directconnect = "directconnect"
    directconnect_with_docs = "directconnect-with-docs"
    discovery = "discovery"
    discovery_with_docs = "discovery-with-docs"
    dlm = "dlm"
    dlm_with_docs = "dlm-with-docs"
    dms = "dms"
    dms_with_docs = "dms-with-docs"
    docdb = "docdb"
    docdb_with_docs = "docdb-with-docs"
    ds = "ds"
    ds_with_docs = "ds-with-docs"
    dynamodb = "dynamodb"
    dynamodb_with_docs = "dynamodb-with-docs"
    dynamodbstreams = "dynamodbstreams"
    dynamodbstreams_with_docs = "dynamodbstreams-with-docs"
    ec2 = "ec2"
    ec2_with_docs = "ec2-with-docs"
    ec2_instance_connect = "ec2-instance-connect"
    ec2_instance_connect_with_docs = "ec2-instance-connect-with-docs"
    ecr = "ecr"
    ecr_with_docs = "ecr-with-docs"
    ecs = "ecs"
    ecs_with_docs = "ecs-with-docs"
    efs = "efs"
    efs_with_docs = "efs-with-docs"
    eks = "eks"
    eks_with_docs = "eks-with-docs"
    elasticache = "elasticache"
    elasticache_with_docs = "elasticache-with-docs"
    elasticbeanstalk = "elasticbeanstalk"
    elasticbeanstalk_with_docs = "elasticbeanstalk-with-docs"
    elastictranscoder = "elastictranscoder"
    elastictranscoder_with_docs = "elastictranscoder-with-docs"
    elb = "elb"
    elb_with_docs = "elb-with-docs"
    elbv2 = "elbv2"
    elbv2_with_docs = "elbv2-with-docs"
    emr = "emr"
    emr_with_docs = "emr-with-docs"
    es = "es"
    es_with_docs = "es-with-docs"
    events = "events"
    events_with_docs = "events-with-docs"
    firehose = "firehose"
    firehose_with_docs = "firehose-with-docs"
    fms = "fms"
    fms_with_docs = "fms-with-docs"
    forecast = "forecast"
    forecast_with_docs = "forecast-with-docs"
    forecastquery = "forecastquery"
    forecastquery_with_docs = "forecastquery-with-docs"
    fsx = "fsx"
    fsx_with_docs = "fsx-with-docs"
    gamelift = "gamelift"
    gamelift_with_docs = "gamelift-with-docs"
    glacier = "glacier"
    glacier_with_docs = "glacier-with-docs"
    globalaccelerator = "globalaccelerator"
    globalaccelerator_with_docs = "globalaccelerator-with-docs"
    glue = "glue"
    glue_with_docs = "glue-with-docs"
    greengrass = "greengrass"
    greengrass_with_docs = "greengrass-with-docs"
    groundstation = "groundstation"
    groundstation_with_docs = "groundstation-with-docs"
    guardduty = "guardduty"
    guardduty_with_docs = "guardduty-with-docs"
    health = "health"
    health_with_docs = "health-with-docs"
    iam = "iam"
    iam_with_docs = "iam-with-docs"
    importexport = "importexport"
    importexport_with_docs = "importexport-with-docs"
    inspector = "inspector"
    inspector_with_docs = "inspector-with-docs"
    iot = "iot"
    iot_with_docs = "iot-with-docs"
    iot_data = "iot-data"
    iot_data_with_docs = "iot-data-with-docs"
    iot_jobs_data = "iot-jobs-data"
    iot_jobs_data_with_docs = "iot-jobs-data-with-docs"
    iot1click_devices = "iot1click-devices"
    iot1click_devices_with_docs = "iot1click-devices-with-docs"
    iot1click_projects = "iot1click-projects"
    iot1click_projects_with_docs = "iot1click-projects-with-docs"
    iotanalytics = "iotanalytics"
    iotanalytics_with_docs = "iotanalytics-with-docs"
    iotevents = "iotevents"
    iotevents_with_docs = "iotevents-with-docs"
    iotevents_data = "iotevents-data"
    iotevents_data_with_docs = "iotevents-data-with-docs"
    iotthingsgraph = "iotthingsgraph"
    iotthingsgraph_with_docs = "iotthingsgraph-with-docs"
    kafka = "kafka"
    kafka_with_docs = "kafka-with-docs"
    kinesis = "kinesis"
    kinesis_with_docs = "kinesis-with-docs"
    kinesis_video_archived_media = "kinesis-video-archived-media"
    kinesis_video_archived_media_with_docs = "kinesis-video-archived-media-with-docs"
    kinesis_video_media = "kinesis-video-media"
    kinesis_video_media_with_docs = "kinesis-video-media-with-docs"
    kinesisanalytics = "kinesisanalytics"
    kinesisanalytics_with_docs = "kinesisanalytics-with-docs"
    kinesisanalyticsv2 = "kinesisanalyticsv2"
    kinesisanalyticsv2_with_docs = "kinesisanalyticsv2-with-docs"
    kinesisvideo = "kinesisvideo"
    kinesisvideo_with_docs = "kinesisvideo-with-docs"
    kms = "kms"
    kms_with_docs = "kms-with-docs"
    lakeformation = "lakeformation"
    lakeformation_with_docs = "lakeformation-with-docs"
    lambda_ = "lambda"
    lambda_with_docs = "lambda-with-docs"
    lex_models = "lex-models"
    lex_models_with_docs = "lex-models-with-docs"
    lex_runtime = "lex-runtime"
    lex_runtime_with_docs = "lex-runtime-with-docs"
    license_manager = "license-manager"
    license_manager_with_docs = "license-manager-with-docs"
    lightsail = "lightsail"
    lightsail_with_docs = "lightsail-with-docs"
    logs = "logs"
    logs_with_docs = "logs-with-docs"
    machinelearning = "machinelearning"
    machinelearning_with_docs = "machinelearning-with-docs"
    macie = "macie"
    macie_with_docs = "macie-with-docs"
    managedblockchain = "managedblockchain"
    managedblockchain_with_docs = "managedblockchain-with-docs"
    marketplace_entitlement = "marketplace-entitlement"
    marketplace_entitlement_with_docs = "marketplace-entitlement-with-docs"
    marketplacecommerceanalytics = "marketplacecommerceanalytics"
    marketplacecommerceanalytics_with_docs = "marketplacecommerceanalytics-with-docs"
    mediaconnect = "mediaconnect"
    mediaconnect_with_docs = "mediaconnect-with-docs"
    mediaconvert = "mediaconvert"
    mediaconvert_with_docs = "mediaconvert-with-docs"
    medialive = "medialive"
    medialive_with_docs = "medialive-with-docs"
    mediapackage = "mediapackage"
    mediapackage_with_docs = "mediapackage-with-docs"
    mediapackage_vod = "mediapackage-vod"
    mediapackage_vod_with_docs = "mediapackage-vod-with-docs"
    mediastore = "mediastore"
    mediastore_with_docs = "mediastore-with-docs"
    mediastore_data = "mediastore-data"
    mediastore_data_with_docs = "mediastore-data-with-docs"
    mediatailor = "mediatailor"
    mediatailor_with_docs = "mediatailor-with-docs"
    meteringmarketplace = "meteringmarketplace"
    meteringmarketplace_with_docs = "meteringmarketplace-with-docs"
    mgh = "mgh"
    mgh_with_docs = "mgh-with-docs"
    mobile = "mobile"
    mobile_with_docs = "mobile-with-docs"
    mq = "mq"
    mq_with_docs = "mq-with-docs"
    mturk = "mturk"
    mturk_with_docs = "mturk-with-docs"
    neptune = "neptune"
    neptune_with_docs = "neptune-with-docs"
    opsworks = "opsworks"
    opsworks_with_docs = "opsworks-with-docs"
    opsworkscm = "opsworkscm"
    opsworkscm_with_docs = "opsworkscm-with-docs"
    organizations = "organizations"
    organizations_with_docs = "organizations-with-docs"
    personalize = "personalize"
    personalize_with_docs = "personalize-with-docs"
    personalize_events = "personalize-events"
    personalize_events_with_docs = "personalize-events-with-docs"
    personalize_runtime = "personalize-runtime"
    personalize_runtime_with_docs = "personalize-runtime-with-docs"
    pi = "pi"
    pi_with_docs = "pi-with-docs"
    pinpoint = "pinpoint"
    pinpoint_with_docs = "pinpoint-with-docs"
    pinpoint_email = "pinpoint-email"
    pinpoint_email_with_docs = "pinpoint-email-with-docs"
    pinpoint_sms_voice = "pinpoint-sms-voice"
    pinpoint_sms_voice_with_docs = "pinpoint-sms-voice-with-docs"
    polly = "polly"
    polly_with_docs = "polly-with-docs"
    pricing = "pricing"
    pricing_with_docs = "pricing-with-docs"
    qldb = "qldb"
    qldb_with_docs = "qldb-with-docs"
    qldb_session = "qldb-session"
    qldb_session_with_docs = "qldb-session-with-docs"
    quicksight = "quicksight"
    quicksight_with_docs = "quicksight-with-docs"
    ram = "ram"
    ram_with_docs = "ram-with-docs"
    rds = "rds"
    rds_with_docs = "rds-with-docs"
    rds_data = "rds-data"
    rds_data_with_docs = "rds-data-with-docs"
    redshift = "redshift"
    redshift_with_docs = "redshift-with-docs"
    rekognition = "rekognition"
    rekognition_with_docs = "rekognition-with-docs"
    resource_groups = "resource-groups"
    resource_groups_with_docs = "resource-groups-with-docs"
    resourcegroupstaggingapi = "resourcegroupstaggingapi"
    resourcegroupstaggingapi_with_docs = "resourcegroupstaggingapi-with-docs"
    robomaker = "robomaker"
    robomaker_with_docs = "robomaker-with-docs"
    route53 = "route53"
    route53_with_docs = "route53-with-docs"
    route53domains = "route53domains"
    route53domains_with_docs = "route53domains-with-docs"
    route53resolver = "route53resolver"
    route53resolver_with_docs = "route53resolver-with-docs"
    s3 = "s3"
    s3_with_docs = "s3-with-docs"
    s3control = "s3control"
    s3control_with_docs = "s3control-with-docs"
    sagemaker = "sagemaker"
    sagemaker_with_docs = "sagemaker-with-docs"
    sagemaker_runtime = "sagemaker-runtime"
    sagemaker_runtime_with_docs = "sagemaker-runtime-with-docs"
    savingsplans = "savingsplans"
    savingsplans_with_docs = "savingsplans-with-docs"
    sdb = "sdb"
    sdb_with_docs = "sdb-with-docs"
    secretsmanager = "secretsmanager"
    secretsmanager_with_docs = "secretsmanager-with-docs"
    securityhub = "securityhub"
    securityhub_with_docs = "securityhub-with-docs"
    serverlessrepo = "serverlessrepo"
    serverlessrepo_with_docs = "serverlessrepo-with-docs"
    service_quotas = "service-quotas"
    service_quotas_with_docs = "service-quotas-with-docs"
    servicecatalog = "servicecatalog"
    servicecatalog_with_docs = "servicecatalog-with-docs"
    servicediscovery = "servicediscovery"
    servicediscovery_with_docs = "servicediscovery-with-docs"
    ses = "ses"
    ses_with_docs = "ses-with-docs"
    shield = "shield"
    shield_with_docs = "shield-with-docs"
    signer = "signer"
    signer_with_docs = "signer-with-docs"
    sms = "sms"
    sms_with_docs = "sms-with-docs"
    sms_voice = "sms-voice"
    sms_voice_with_docs = "sms-voice-with-docs"
    snowball = "snowball"
    snowball_with_docs = "snowball-with-docs"
    sns = "sns"
    sns_with_docs = "sns-with-docs"
    sqs = "sqs"
    sqs_with_docs = "sqs-with-docs"
    ssm = "ssm"
    ssm_with_docs = "ssm-with-docs"
    stepfunctions = "stepfunctions"
    stepfunctions_with_docs = "stepfunctions-with-docs"
    storagegateway = "storagegateway"
    storagegateway_with_docs = "storagegateway-with-docs"
    sts = "sts"
    sts_with_docs = "sts-with-docs"
    support = "support"
    support_with_docs = "support-with-docs"
    swf = "swf"
    swf_with_docs = "swf-with-docs"
    textract = "textract"
    textract_with_docs = "textract-with-docs"
    transcribe = "transcribe"
    transcribe_with_docs = "transcribe-with-docs"
    transfer = "transfer"
    transfer_with_docs = "transfer-with-docs"
    translate = "translate"
    translate_with_docs = "translate-with-docs"
    waf = "waf"
    waf_with_docs = "waf-with-docs"
    waf_regional = "waf-regional"
    waf_regional_with_docs = "waf-regional-with-docs"
    workdocs = "workdocs"
    workdocs_with_docs = "workdocs-with-docs"
    worklink = "worklink"
    worklink_with_docs = "worklink-with-docs"
    workmail = "workmail"
    workmail_with_docs = "workmail-with-docs"
    workmailmessageflow = "workmailmessageflow"
    workmailmessageflow_with_docs = "workmailmessageflow-with-docs"
    workspaces = "workspaces"
    workspaces_with_docs = "workspaces-with-docs"
    xray = "xray"
    xray_with_docs = "xray-with-docs"

    @classmethod
    def items(cls) -> List[ServiceName]:
        return list(cls)

    @classmethod
    def values(cls) -> List[str]:
        return [i.value for i in cls]

    @property
    def module_name(self) -> str:
        return f"{MODULE_NAME}_{self.name}".rstrip("_")

    @property
    def extras_name(self) -> str:
        return self.value

    @property
    def fallback(self) -> ServiceName:
        if not self.is_with_docs():
            return self

        return ServiceName(str(self.value).replace(WITH_DOCS_PYPI_POSTFIX, ""))

    @property
    def import_name(self) -> str:
        return self.fallback.name

    @property
    def pypi_name(self) -> str:
        return f"{PYPI_NAME}-{self.value}"

    def is_essential(self) -> bool:
        return self.value in [
            ServiceName.ec2.value,
            ServiceName.rds.value,
            ServiceName.s3.value,
            ServiceName.lambda_.value,
            ServiceName.sqs.value,
            ServiceName.cloudformation.value,
        ]

    def is_with_docs(self) -> bool:
        return str(self.name).endswith("_with_docs")

    @property
    def boto3_name(self) -> str:
        if self.is_with_docs():
            return str(self.value).replace(WITH_DOCS_PYPI_POSTFIX, "")

        return self.value


def main() -> None:
    for item in ServiceName.items():
        link = f"https://pypi.org/project/{item.pypi_name}/"
        if item.is_with_docs():
            description = (
                f"Type annotations for `boto3` [{item.boto3_name}]({link})"
                " service with included documentation."
            )
        else:
            description = (
                f"Type annotations for `boto3` [{item.boto3_name}]({link}) service."
            )
        print(f"- `{item.value}` - {description}")


if __name__ == "__main__":
    main()
