import os, sys, json
from python_helper.api.src.service import StringHelper, LogHelper, ObjectHelper, SettingHelper
from python_helper.api.src.domain import Constant as c

OS = os
SYS = sys
OS_SEPARATOR = OS.path.sep

LINUX_OS_NAME = 'linux'
WINDOWS_OS_NAME = 'win32'

clear = lambda: OS.system('cls')

def get(environmentKey, default=None) :
    environmentValue = default if ObjectHelper.isNone(environmentKey) else OS.environ.get(environmentKey)
    return environmentValue if ObjectHelper.isNotNone(environmentValue) else default

def update(environmentKey, environmentValue, default=None) :
    if ObjectHelper.isNotEmpty(environmentKey) :
        associatedValue = None
        if ObjectHelper.isNotNone(environmentValue):
            associatedValue = str(StringHelper.filterString(environmentValue))
            OS.environ[environmentKey] = associatedValue
        elif ObjectHelper.isNotNone(default):
            associatedValue = str(StringHelper.filterString(default))
            OS.environ[environmentKey] = associatedValue
        else :
            try:
                delete(environmentKey)
            except Exception as exception :
                LogHelper.warning(update, f'Failed to delete enviroment variable key "{environmentKey}" while updating it to "{environmentValue}"', exception=exception)
        return associatedValue
    else :
        LogHelper.debug(update, f'arguments: environmentKey: {environmentKey}, environmentValue: {environmentValue}, default: {default}')
        raise Exception(f'Error associating environment variable "{environmentKey}" key to environment variable "{environmentValue}" value')

def switch(environmentKey, environmentValue, default=None) :
    originalEnvironmentValue = get(environmentKey, default=default)
    update(environmentKey, environmentValue, default=default)
    return originalEnvironmentValue

def reset(environmentVariables, originalEnvironmentVariables) :
    if environmentVariables :
        for key in environmentVariables.keys() :
            if key in originalEnvironmentVariables :
                update(key, originalEnvironmentVariables[key])

def delete(environmentKey) :
    if ObjectHelper.isNotNone(environmentKey) :
        OS.environ.pop(environmentKey)

def getSet(avoidRecursiveCall=False) :
    try :
        return {key : OS.environ[key] for key in OS.environ}
    except Exception as exception :
        LogHelper.error(getSet, 'Not possible to load os.environ as a json. Returning os.environ as string by default', exception)
        return str(OS.environ)[8:-1]

def isNone(environmentKey, default=True, evaluateItInsted=None):
    if ObjectHelper.isNotNone(environmentKey) :
        return c.NONE == (
            evaluateItInsted if ObjectHelper.isNotNone(evaluateItInsted) else get(environmentKey, default=c.NONE)
        )
    return default

def isNotNone(environmentKey, default=True, evaluateItInsted=None):
    if ObjectHelper.isNotNone(environmentKey) :
        return not c.NONE == (
            evaluateItInsted if ObjectHelper.isNotNone(evaluateItInsted) else get(environmentKey, default=c.NONE)
        )
    return default

def isBoolean(environmentKey, default=False, evaluateItInsted=None):
    if ObjectHelper.isNotNone(environmentKey) :
        if ObjectHelper.isNotNone(evaluateItInsted):
            return evaluateItInsted in [c.TRUE, c.FALSE] if isNotNone(environmentKey, evaluateItInsted=evaluateItInsted) else default
        return get(environmentKey, default=default) in [c.TRUE, c.FALSE]
    return default

def isTrue(environmentKey, default=False, evaluateItInsted=None):
    if ObjectHelper.isNotNone(environmentKey) :
        if ObjectHelper.isNotNone(evaluateItInsted):
            return c.TRUE == evaluateItInsted if isBoolean(environmentKey, default=default, evaluateItInsted=evaluateItInsted) else default
        innerEvaluatItInsted = get(environmentKey, default=None)
        if ObjectHelper.isNotNone(innerEvaluatItInsted):
            return isTrue(environmentKey, default=default, evaluateItInsted=innerEvaluatItInsted)
        if isBoolean(environmentKey, evaluateItInsted=innerEvaluatItInsted):
            return c.TRUE == c.TRUE if isinstance(default, bool) and default else c.FALSE
    return default

def isFalse(environmentKey, default=True, evaluateItInsted=None):
    # if ObjectHelper.isNotNone(environmentKey) :
    #     innerEvaluatItInsted = get(environmentKey, default=None)
    #     if ObjectHelper.isNotNone(evaluateItInsted):
    #         return c.FALSE == evaluateItInsted if isBoolean(environmentKey, evaluateItInsted=innerEvaluatItInsted) else default
    #     if isBoolean(environmentKey):
    #         return c.FALSE == c.FALSE if isinstance(default, bool) and not default else c.TRUE
    # return default


    if ObjectHelper.isNotNone(environmentKey) :
        if ObjectHelper.isNotNone(evaluateItInsted):
            return c.FALSE == evaluateItInsted if isBoolean(environmentKey, default=default, evaluateItInsted=evaluateItInsted) else default
        innerEvaluatItInsted = get(environmentKey, default=None)
        if ObjectHelper.isNotNone(innerEvaluatItInsted):
            return isTrue(environmentKey, default=default, evaluateItInsted=innerEvaluatItInsted)
        if isBoolean(environmentKey, evaluateItInsted=innerEvaluatItInsted):
            return c.FALSE == c.FALSE if isinstance(default, bool) and not default else c.TRUE
    return default

def listDirectoryContent(path) :
    return OS.listdir(path)

def isDirectory(path) :
    return OS.path.isdir(path)

def isFile(path) :
    return OS.path.isfile(path)

def makeDirectory(path, accessRights=0o777) :
    ###- accessRights = 0o777 --> write, access and read
    ###- accessRights = 0o755 --> access and read
    ###- accessRights = 0o755 --> access and read
    OS.makedirs(path, mode=accessRights)

def appendPath(path) :
    SYS.path.append(path)

def getCurrentSoutStatus(avoidRecursiveCall=False) :
    return SYS.stdout, SYS.stderr

def overrideSoutStatus(stdout, stderr) :
    SYS.stdout = stdout
    SYS.stderr = stderr

def isLinux() :
    return SYS.platform == LINUX_OS_NAME

def isWindows() :
    return SYS.platform == WINDOWS_OS_NAME
