# -*- coding: utf-8 -*-
# Copyright (c) 2017 CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

"""
Contains functions for efficiently extracting parts of a CZRN.
CZRNs are used to unambiguously and uniquely identify any resource from any cloud provider, and even covers cases
where a resource might be observed from the Internet, and resources which may not have explicit existence
in a cloud environment.
"""
from functools import partial

from czid.czrn.validate import CZRN_CAPTURE_REGEX

COMPONENT_ENUM = {'service': 2, 'region': 3, 'account_id': 4, 'resource_type': 5, 'cloud_local_id': 6}


def fast_extract_components(czrn, component=None):
    """
    Quickly extract the components of a CZRN, for use when performance vs. safety is the priority.

    Optionally use `component` to return only the part you need, or use the handy partials below

    Performance for 10,000 executions
        fast_extract_components : 0.054163192999999055
        extract_all_components  : 0.24722171600000564

    Args:
        component (str): If desired, return only a specific part
        czrn (str): a CZRN string

    >>> fast_extract_components('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    ['ec2', 'us-east-1', '123456789012', 'dedicated-host', 'h-12345678/foo:bar']

    >>> fast_extract_components('czrn:aws:s3:cross-region:unknown-account:bucket:my-bucket')
    ['s3', 'cross-region', 'unknown-account', 'bucket', 'my-bucket']

    >>> fast_extract_components('czrn:aws:s3:cross-region:unknown-account:bucket:my-bucket', component='region')
    'cross-region'

    >>> fast_extract_components('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar', \
                                component='cloud_local_id')
    'h-12345678/foo:bar'

    Returns:
        List: the components of the provider CZRN: service_type, region, account_id, resource_type, cloud_local_id
    """
    try:
        if component:
            return czrn.split(":", 6)[COMPONENT_ENUM[component]]
        else:
            return czrn.split(":", 6)[2:]
    except (ValueError, AttributeError):
        raise ValueError(f"CZRN '{czrn}' is not valid")


fast_extract_service_type = partial(fast_extract_components, component='service')
fast_extract_region = partial(fast_extract_components, component='region')
fast_extract_account_id = partial(fast_extract_components, component='account_id')
fast_extract_resource_type = partial(fast_extract_components, component='resource_type')
fast_extract_cloud_local_id = partial(fast_extract_components, component='cloud_local_id')


def extract_all_components(czrn):
    """
    Extract and return all of the components of a CZRN as a tuple.

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        5-tuple of strings - the components of the provider CZRN: service_type, region, account_id,
                             resource_type, cloud_local_id.
    >>> extract_all_components('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    ('ec2', 'us-east-1', '123456789012', 'dedicated-host', 'h-12345678/foo:bar')

    >>> extract_all_components('czrn:aws:s3:cross-region:unknown-account:bucket:my-bucket')
    ('s3', 'cross-region', 'unknown-account', 'bucket', 'my-bucket')

    >>> extract_all_components('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    czrn_match = CZRN_CAPTURE_REGEX.fullmatch(czrn) if czrn else None
    if not czrn_match:
        raise ValueError(f'CZRN {czrn} is not valid')
    service, region, account_id, resource_type, cloud_local_id = czrn_match.groups()
    return service, region, account_id, resource_type, cloud_local_id


def extract_service_type(czrn):
    """
    Extract and return service type from a CZRN

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        str - The service type

    >>> extract_service_type('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    'ec2'

    >>> extract_service_type('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    service, _, _, _, _ = extract_all_components(czrn)
    return service


def extract_resource_type(czrn):
    """
    Extract and return service type from a CZRN

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        str - The service type

    >>> extract_resource_type('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    'dedicated-host'

    >>> extract_resource_type('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    _, _, _, resource_type, _ = extract_all_components(czrn)
    return resource_type


def extract_cloud_local_id(czrn):
    """
    Extract and return service type from a CZRN

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        str - The service type
    >>> extract_cloud_local_id('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    'h-12345678/foo:bar'

    >>> extract_cloud_local_id('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    _, _, _, _, cloud_local_id = extract_all_components(czrn)
    return cloud_local_id


def extract_region(czrn):
    """
    Extract and return service type from a CZRN

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        str - The service type

    >>> extract_region('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    'us-east-1'

    >>> extract_region('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    _, region, _, _, _ = extract_all_components(czrn)
    return region


def extract_account_id(czrn):
    """
    Extract and return service type from a CZRN

    Args:
        czrn (str): The CZRN to unpack

    Returns:
        str - The service type

    >>> extract_account_id('czrn:aws:ec2:us-east-1:123456789012:dedicated-host:h-12345678/foo:bar')
    '123456789012'

    >>> extract_account_id('foobar')
    Traceback (most recent call last):
    ...
    ValueError: CZRN foobar is not valid
    """
    _, _, account_id, _, _ = extract_all_components(czrn)
    return account_id
