# Copyright 2023 Canonical Ltd.
# Licensed under the Apache V2, see LICENCE file for details.

import re
from enum import Enum, unique


@unique
class MatchType(Enum):
    MATCH = 1
    SEARCH = 2


MODEL = re.compile("^[a-z0-9]+[a-z0-9-]*$")


def match_model(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(MODEL, val)
    else:
        return re.match(MODEL, val)


APPLICATION = re.compile("^(?:[a-z][a-z0-9]*(?:-[a-z0-9]*[a-z][a-z0-9]*)*)$")


def match_application(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(APPLICATION, val)
    else:
        return re.match(APPLICATION, val)


def is_valid_application(val):
    return match_application(val) is not None


ENDPOINT = re.compile(
    "/?((?P<model>[^\\.]*)\\.)?(?P<appname>[^:]*)(:(?P<endpoints>.*))?"
)


def match_endpoint(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(ENDPOINT, val)
    else:
        return re.match(ENDPOINT, val)


SOURCE_ENDPOINT = re.compile("^[a-zA-Z0-9]+$")


def match_source_endpoint(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(SOURCE_ENDPOINT, val)
    else:
        return re.match(SOURCE_ENDPOINT, val)


MODEL_APPLICATION = re.compile(
    "(/?((?P<user>[^/]+)/)?(?P<model>[^.]*)(.(?P<application>[^:]*(:.*)?))?)?"
)


def match_model_application(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(MODEL_APPLICATION, val)
    else:
        return re.match(MODEL_APPLICATION, val)


valid_user_name_snippet = "[a-zA-Z0-9][a-zA-Z0-9.+-]*[a-zA-Z0-9]"
valid_user_snippet = f"(?:{valid_user_name_snippet}(?:@{valid_user_name_snippet})?)"
USER = re.compile(
    f"^(?P<name>{valid_user_name_snippet})(?:@(?P<domain>{valid_user_name_snippet}))?$"
)


def match_user(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(USER, val)
    else:
        return re.match(USER, val)


RELATION = re.compile("[a-z][a-z0-9]*(?:[_-][a-z0-9]+)*")


def match_relation(val, match_type=None):
    if match_type is MatchType.SEARCH:
        return re.search(RELATION, val)
    else:
        return re.match(RELATION, val)
