import posixpath
from six.moves import urllib

from segmind.exceptions import MlflowException
from segmind.protos.errorcodes_pb2 import INVALID_PARAMETER_VALUE
# from segmind.store.db.db_types import DATABASE_ENGINES
from segmind.utils.validation import _validate_db_type_string

_INVALID_DB_URI_MSG = 'Please refer to https://segmind_track.org/docs/latest'\
                      '/tracking.html#storage for format specifications.'


def is_local_uri(uri):
    """Returns true if this is a local file path (/foo or file:/foo)."""
    scheme = urllib.parse.urlparse(uri).scheme
    return uri != 'databricks' and (scheme == '' or scheme == 'file')


def is_http_uri(uri):
    scheme = urllib.parse.urlparse(uri).scheme
    return scheme == 'http' or scheme == 'https'


def is_databricks_uri(uri):
    """Databricks URIs look like 'databricks' (default profile) or
    'databricks://profile'."""
    scheme = urllib.parse.urlparse(uri).scheme
    return scheme == 'databricks' or uri == 'databricks'


def get_db_profile_from_uri(uri):
    """Get the Databricks profile specified by the tracking URI (if any),
    otherwise returns None."""
    parsed_uri = urllib.parse.urlparse(uri)
    if parsed_uri.scheme == 'databricks':
        return parsed_uri.netloc
    return None


def extract_db_type_from_uri(db_uri):
    """Parse the specified DB URI to extract the database type.

    Confirm the database type is supported. If a driver is specified, confirm
    it passes a plausible regex.
    """
    scheme = urllib.parse.urlparse(db_uri).scheme
    scheme_plus_count = scheme.count('+')

    if scheme_plus_count == 0:
        db_type = scheme
    elif scheme_plus_count == 1:
        db_type, _ = scheme.split('+')
    else:
        error_msg = "Invalid database URI: '%s'. %s" % (db_uri,
                                                        _INVALID_DB_URI_MSG)
        raise MlflowException(error_msg, INVALID_PARAMETER_VALUE)

    _validate_db_type_string(db_type)

    return db_type


def get_uri_scheme(uri_or_path):
    scheme = urllib.parse.urlparse(uri_or_path).scheme
    # if any([scheme.lower().startswith(db) for db in DATABASE_ENGINES]):
    #     return extract_db_type_from_uri(uri_or_path)
    # else:
    return scheme


def append_to_uri_path(uri, *paths):
    """Appends the specified POSIX `paths` to the path component of the
    specified `uri`."""
    path = ''
    for subpath in paths:
        path = _join_posixpaths_and_append_absolute_suffixes(path, subpath)

    parsed_uri = urllib.parse.urlparse(uri)
    if len(parsed_uri.scheme) == 0:
        # If the input URI does not define a scheme, we assume that it is a
        # POSIX path and join it with the specified input paths
        return _join_posixpaths_and_append_absolute_suffixes(uri, path)

    prefix = ''
    if not parsed_uri.path.startswith('/'):
        # For certain URI schemes (e.g., "file:"), urllib's unparse routine
        # does not preserve the relative URI path component properly. In
        # certain cases, urlunparse converts relative paths to absolute paths.
        # We introduce this logic to circumvent urlunparse's erroneous
        # conversion
        prefix = parsed_uri.scheme + ':'
        parsed_uri = parsed_uri._replace(scheme='')

    new_uri_path = _join_posixpaths_and_append_absolute_suffixes(
        parsed_uri.path, path)
    new_parsed_uri = parsed_uri._replace(path=new_uri_path)
    return prefix + urllib.parse.urlunparse(new_parsed_uri)


def _join_posixpaths_and_append_absolute_suffixes(prefix_path, suffix_path):
    """Joins the POSIX path `prefix_path` with the POSIX path `suffix_path`.

    Unlike posixpath.join(), if `suffix_path` is an absolute path, it is
    appended to prefix_path.
    """
    if len(prefix_path) == 0:
        return suffix_path

    # If the specified prefix path is non-empty, we must relativize the suffix
    # path by removing the leading slash, if present. Otherwise,
    # posixpath.join() would omit the prefix from the joined path
    suffix_path = suffix_path.lstrip(posixpath.sep)
    return posixpath.join(prefix_path, suffix_path)
