"""
Django settings for aimdb project.

Generated by 'django-admin startproject' using Django 3.0.5.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

from pathlib import Path
import os, sys, glob
from django.urls import path, include
import logging
from django.utils.log import DEFAULT_LOGGING

# --------------------------------------------------------------------------------------
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = Path(".")
THIS_BASE_DIR = Path(__file__).resolve(strict=True)  # Where settings.py is located


# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'pr75j7t*r!j=oac!798tazlecdo0%k0rasre@!f_&0u%2(=nty'
DEFAULT_DOMAIN = "https://www.example.org"
CSRF_TRUSTED_ORIGINS = ['https://*.127.0.0.1']

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DATA_UPLOAD_MAX_MEMORY_SIZE = 5242880
ALLOWED_HOSTS = ['*', 'localhost']

LOGIN_REDIRECT_URL_FAILURE="/djangoui/not_authorized.html"

# Authentication Settings
LOGIN_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
SESSION_SAVE_EVERY_REQUEST = True
SOCIALACCOUNT_STORE_TOKENS=True

# --------------------------------------------------------------------------------------
AUTO_LOGOUT_DELAY=30000

#ACCOUNT_AUTHENTICATION_METHOD="username_email"
#ACCOUNT_LOGIN_METHODS
#ACCOUNT_USERNAME_REQUIRED=False
#ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window
#ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS=7
#ACCOUNT_EMAIL_REQUIRED = True
#ACCOUNT_SIGNUP_FIELDS = ['email*', 'password1*', 'password2*']
#ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT=86400000000
#ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_USERNAME_MIN_LENGTH = 3
ACCOUNT_EMAIL_SUBJECT_PREFIX="From: "
ACCOUNT_DEFAULT_HTTP_PROTOCOL="https"

X_FRAME_OPTIONS = 'SAMEORIGIN'
XS_SHARING_ALLOWED_METHODS = ['POST','GET','OPTIONS', 'PUT', 'DELETE']


def appcontext(request):
    context = {
        "appname"           : "DEFAULT EXAMPLE",
        "weburl"            : "https://Your URL/",
        #"top_url"           : "",
        #"entire_top_url"    : "app/topbar.html",      # If you want the entire top URL replaced
        "NO_LOGIN_MENU"     : 1,                       # 1: to show login menu in topbar right corner
        "APP_MENU"          : 0,                       # 1: show applications menu in top bar
        "SSO"               : 0,                       # 1: to show single signon during login
        "DO_NOT_SHOW_LOGIN" : 1,                       # 1: do not allow users to enter username/passwd
        "ALLOW_REGISTRATION": 0,                       # 1: allow users to register
    }

    return context

# --------------------------------------------------------------------------------------
# Disable Django's logging setup
LOGGING_CONFIG = None

LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
LOGFILE  = os.environ.get('LOGFILE', 'logs/app.log')
if not os.path.exists('logs'):
    os.mkdir("logs")

logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'default': {
            # exact format is not important, this is the minimum information
            'format': '%(levelname)s:%(name)s %(asctime)-12s %(filename)s:%(lineno)s:%(funcName)s: %(message)s',
        },
        #'django.server': DEFAULT_LOGGING['formatters']['django.server'],
    },
    'handlers': {
        # console logs to stderr
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
        },
        "file": {
            "class": "logging.FileHandler",
            "filename": LOGFILE,
        },
        #'django.server': DEFAULT_LOGGING['handlers']['django.server'],
    },
    'loggers': {
        # default for all undefined Python modules
        '': {
            'level': LOGLEVEL,
            'handlers': [], # ['console'],
            'propagate': False,
        },
        '.': {
            'level': LOGLEVEL,
            'handlers': ['console'],
            'propagate': False,
        },
        'app': {
            'level': LOGLEVEL,
            'handlers': ['console'],
            'propagate': False,
        },
        # Our application code
        'djangoui': {
            'level': LOGLEVEL,
            'handlers': ['console', 'file'  ],
            # Avoid double logging because of root logger
            'propagate': False,
        },
        'django.server': {
            'level': 'WARNING',
            'handlers': ['console'  ],
            'propagate': False,
        },
        'uvicorn': {
            'level': 'WARNING',
            'handlers': ['console'  ],
            'propagate': False,
        }
        # Default runserver request logging
        #'django.server': DEFAULT_LOGGING['loggers']['django.server'],
    },
})
#------------------------------------------------------------------------------
for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)
    
logging.basicConfig( level=logging.INFO,
        format='%(levelname)s:%(name)s %(asctime)s %(filename)s:%(lineno)s:%(funcName)s: %(message)s',
        handlers=[ logging.FileHandler("/tmp/djangoui.log"), logging.StreamHandler()],
        #handlers=[ logging.StreamHandler()],
)
logger = logging.getLogger("app")

LOGLEVELS = os.environ.get('LOGLEVELS', '')
for l in LOGLEVELS.split(":"):
    nv = l.split("=")

    if ( len(nv) !=2):
        continue
    n, v = nv
    gl = logging.getLogger(n)
    gl.setLevel(v.upper())

#------------------------------------------------------------------------------
AUTHENTICATION_BACKENDS = [
    'djangoui.myoidc.MyOIDCAB',
    
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'oauth2_provider.middleware.OAuth2TokenMiddleware',
    'allauth.account.middleware.AccountMiddleware'
]

# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
#    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},
#    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},
#    {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},
#    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},
]

# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N  = True
USE_L10N  = True
USE_TZ    = True

#EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
CORS_ORIGIN_ALLOW_ALL = True   
#------------------------------------------------------------------------------
ROOT_URLCONF = 'djangoui.urls'
WSGI_APPLICATION = 'djangoui.wsgi.application'
ASGI_APPLICATION = 'djangoui.asgi.application'

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_extensions',
    'oauth2_provider',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'djangoui',
 ]
 #---------------------------------------------------------------------------------  
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'default_pg': { # You can set these in your my_config.p
        'ENGINE':   'django.db.backends.postgresql',
        'NAME':     'DATABASE_NAME',
        'USER':     'DATABASE_USER',
        'PASSWORD': 'DATABASE_PASSWORD',
        'HOST':     'DATABASE_HOST', # For local development, use 'localhost' or '127.0.0.1'
        'PORT':     'DATABASE_PORT', # Default PostgreSQL port is usually '5432' 
    }
}

STATIC_URL = '/static/'
SITE_ID = 1

DETECT_INSTALLED_APPS = False
DETECTED_APPS = []
DETECTED_URLS = []
INCLUDE_APPS  = []
INCLUDE_APPS_URLS = [] # used in urls.py to include urls
#------------------------------------------------------------------------------
sys.path.append(os.path.expanduser("~/.django") )
if (os.path.exists("my_config.py")):
    #print("\n++++++++++\nFound local settings - including local settings\n\n")
    import my_config
    from my_config import *
elif (os.path.exists(os.path.expanduser("~/.django/my_config.py"))):
    import my_config
    from my_config import *

#---------------------------------------------------------------------------------
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'mainapp/templates'), os.path.join(BASE_DIR, 'templates'),
                 os.path.join(THIS_BASE_DIR.parent, 'templates'),],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'djangoui.settings.appcontext'
            ],
        },
    },
]
#------------------------------------------------------------------------------
def detectInstalledApps(appslist):
    global DETECTED_URLS

    logger.info (f"++ Searching for APPS ... {len(DETECTED_APPS)} PID {os.getpid()}")
    appmenu = ""
    for file in glob.glob("**/apps.py"):
        app = os.path.basename(os.path.dirname(file))

        logger.info(f"FOUND ** {file} {app}")
        DETECTED_APPS.append(app) 
        
        index_template = f'{app}/templates/{app}/index.html'
        if ( not os.path.exists(index_template) ):
            index_template = f'{app}/templates/index.html'
        if ( not os.path.exists(index_template) ):
            index_template = f'{app}/templates/{app}.html'
        if ( not os.path.exists(index_template) ):
            index_template = f'{app}/templates/secured/{app}/index.html'
        if ( not os.path.exists(index_template) ):
            index_template = f'{app}/{app}/'

        # ADD ONLY IF INDEX TEMPLATE EXISTS - OTHERWISE IT IS NOT A WEB APP
        if ( os.path.exists(index_template) ):
            index = index_template.replace("/templates/", "/")
            appmenu += f'''<a class="dropdown-item" href="/{index}" > {app} </a>\n '''

    logger.debug(f"-======>DETECTED:  {DETECTED_APPS}")
    if ( len(DETECTED_APPS) > 0): 
        DETECTED_URLS = [ path(f'{a}/', include(f'{a}.urls'), name=a) for a in DETECTED_APPS ]
        logger.debug (f"-- Detected {len(DETECTED_APPS)} apps: {DETECTED_APPS}")

    if os.path.exists("templates/appmenu.html"):        
        with open("templates/appmenu.html", "w+" ) as f:
            f.write(appmenu)
        
    return DETECTED_APPS;

if ( DETECT_INSTALLED_APPS ):
    detectInstalledApps(INSTALLED_APPS)
# -----------------------------------------------------------------------------------------
DETECTED_APPS += INCLUDE_APPS
INSTALLED_APPS = INSTALLED_APPS + DETECTED_APPS

# Include URLS 
DETECTED_URLS = [ path(f'{a}/', include(f'{a}.urls'), name=a) for a in INCLUDE_APPS ]
if (os.path.exists("mainapp") and 'mainapp' not in INSTALLED_APPS):
    INSTALLED_APPS += ['mainapp'] 
    DETECTED_URLS += [path(f'mainapp/', include(f'mainapp.urls'), name='mainapp') ]



STATIC_INSTALL_DIRS = [ f'{BASE_DIR}/{c}/static/'  for c in DETECTED_APPS 
                            if os.path.exists(f'{BASE_DIR}/{c}/static/') ]

STATICFILES_DIRS = [ THIS_BASE_DIR.parent / 'static/' ] + STATIC_INSTALL_DIRS


INSTALLED_APPS += ['channels']
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer',
    },
}
# -----------------------------------------------------------------------------------------
