from functools import wraps
from pathlib import Path
from pyparsing import *
import dateutil.parser
import requests
import click
import copy
import json
import os


class auth:

    def get_profile(config_data, name):
        return config_data['profiles'].get(name)

    def get_env(config_data, name):
        return config_data['envs'].get(name)

    def set_cache(data):
        clean_data = auth.sanatize_data(data)
        with open(auth.get_cache_file(), 'w+') as outfile:
            json.dump(data, outfile, indent=4, sort_keys=True)

    def clear_cache():
        with open(auth.get_cache_file(), 'w+') as outfile:
            json.dump({}, outfile, indent=4, sort_keys=True)

    def set_cache_token(token):
        cache = auth.load_cache()
        cache['accessToken'] = token
        auth.set_cache(cache)

        return cache

    def get_profile_names(ctx, args, incomplete):
        config = auth.load_config()
        names = config['profiles'].keys()
        return [k for k in names if incomplete in k]

    def sanatize_data(data):
        return { k:v.replace(" ", "") if isinstance(v, str) and k != 'orgName' else v for k,v in data.items() }

    def set_profile_token(profile, token):
        config_data = auth.load_config()
        config_data['profiles'][profile]['accessToken'] = token
        auth.save_config(config_data)

        return config_data

    def get_cache_file():
        cache_path = str(Path.home()) + '/.luma_cache'
        if not os.path.exists(cache_path):
            with open(cache_path, 'w+') as cache:
                json.dump({}, cache)

        return cache_path

    def load_cache():
        with open(auth.get_cache_file()) as json_file:
            data = json.load(json_file)

        return data

    def save_config(data):
        with open(auth.get_config_file(), 'w+') as outfile:
            json.dump(data, outfile, indent=4, sort_keys=True)

    def load_config():
        try:
            with open(auth.get_config_file()) as json_file:
                data = json.load(json_file)
            return data
        except Exception as e:
            print('No config file or bad config file found. Making a new one.')
            auth.save_config({ "envs": {}, "profiles": {} })

            return {
                "envs": {},
                "profiles": {}
            }

    def get_config_file():
        config_path = str(Path.home()) + '/.luma_cli_config'
        if not os.path.exists(config_path):
            with open(config_path, 'w') as config:
                json.dump({ "envs": {}, "profiles": {} }, config)

        return config_path

    def profile_context_required(f):
        @wraps(f)
        def decorated_func(*args, **kwargs):
            try:
                profile = kwargs.get('profile')
                config_data = auth.load_config()
                profile_data = auth.get_profile(config_data, profile)

                if profile_data is None:
                    raise click.BadParameter(click.style('You must provide the name of a profile that you have configured', fg='red'))
                if profile_data.get('orgId') is None or profile_data.get('orgId') == '':
                    raise click.BadParameter(click.style('You must finish configuring this profile before you can use it', fg='red'))

                clean_data = auth.sanatize_data(profile_data)

                clean_data['profileName'] = profile
                env_data = auth.sanatize_data(auth.get_env(config_data, clean_data.get('env')))

                cache_data = {**clean_data, **env_data}

                # Protect against error state where 'accessToken' would become null
                if cache_data.get("accessToken") is None:
                    cache_data['accessToken'] = " "

                auth.set_cache(cache_data)

            except Exception as e:
                click.echo(click.style(str(e), fg='red'))
                raise click.Abort()

            f(*args, **kwargs)
            auth.clear_cache()

            return
        return decorated_func
