import random
import string as string_module  # pylint: disable=deprecated-module
import urllib.parse

from django.apps import apps
from django.conf import settings
from django.http import QueryDict

# TODO: Remove legacy apps and this filtering step.

def querydict_from_dict(input_dict):
    Given a dict, return a QueryDict.
    querydict = QueryDict("", mutable=True)

    return querydict

def full_url(url_fragment):
    Given a fragment, return that fragment joined to the full Open Humans URL.
    if url_fragment and not url_fragment.startswith("/"):
        return url_fragment

    return urllib.parse.urljoin(
        settings.DEFAULT_HTTP_PROTOCOL + "://" + settings.DOMAIN, str(url_fragment)

def get_source_labels_and_configs():
    Return a list of all current data source app labels and names.
    sources = [
        (app_config.label, app_config)
        for app_config in apps.get_app_configs()

    sources = [x for x in sources if x[0] not in LEGACY_APPS]

    return sorted(sources, key=lambda x: x[1].verbose_name.lower())

def get_activities():
    Get just the activities.
    return [
        for activity in get_source_labels_and_configs()
        if activity[1].name.startswith("activities.")

def get_studies():
    Get just the studies.
    return [
        for study in get_source_labels_and_configs()
        if study[1].name.startswith("studies.")

def get_source_labels_and_names():
    Return a list of all current data source app labels and names.
    return [
        (label, app_config.verbose_name)
        for label, app_config in get_source_labels_and_configs()

def get_source_labels():
    Return a list of all current data source app labels.
    # Use get_source_labels_and_names so labels are sorted by verbose names
    return [label for label, _ in get_source_labels_and_names()]

def app_label_to_app_models(label):
    Given an app's name, return its models.
    return apps.get_app_config(label).get_models()

def app_label_to_verbose_name(label):
    Given an app's name, return its verbose name.
    return apps.get_app_config(label).verbose_name

def app_label_to_user_data_model(label):
    Given an app name, return its UserData type.
    for model in app_label_to_app_models(label):
        if (
            model.__base__.__name__ == "BaseStudyUserData"
            or model.__name__ == "UserData"
            return model

    app = apps.get_app_config(label)

    if hasattr(app, "user_data"):
        return app.user_data()

def generate_id(
        + string_module.ascii_uppercase
        + string_module.digits
    Generate an ID consisting of upper and lowercase letters and digits.
    return "".join(random.SystemRandom().choice(chars) for _ in range(size))

def origin(string):
    Coerce an origin to 'open-humans' or 'external', defaulting to 'external'
    return "open-humans" if string == "open-humans" else "external"