from dotenv import load_dotenv
from flask import Flask
from logging.handlers import RotatingFileHandler
from werkzeug.middleware.proxy_fix import ProxyFix
import logging
import os


basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))


class Config:
    ''' Docker '''
    DOCKER_NETWORK_NAME = os.environ.get('DOCKER_NETWORK_NAME', 'nopaque_default')

    ''' APIFairy '''
    APIFAIRY_TITLE = 'nopaque'
    APIFAIRY_VERSION = '0.0.1'
    APIFAIRY_UI = 'swagger_ui'
    APIFAIRY_APISPEC_PATH = '/api/apispec.json'
    APIFAIRY_UI_PATH = '/api'

    ''' # Flask # '''
    PREFERRED_URL_SCHEME = os.environ.get('PREFERRED_URL_SCHEME', 'http')
    SECRET_KEY = os.environ.get('SECRET_KEY', 'hard to guess string')
    SERVER_NAME = os.environ.get('SERVER_NAME', 'localhost:5000')
    SESSION_COOKIE_SECURE = \
        os.environ.get('SESSION_COOKIE_SECURE', 'false').lower() == 'true'

    ''' # Flask-APScheduler # '''
    JOBS = []

    ''' # Flask-Assets '''
    ASSETS_DEBUG = os.environ.get('ASSETS_DEBUG', 'false').lower() == 'true'

    ''' # Flask-Hashids '''
    HASHIDS_MIN_LENGTH = 16
    HASHIDS_SALT=os.environ.get('HASHIDS_SALT')

    ''' # Flask-Login # '''
    REMEMBER_COOKIE_SECURE = \
        os.environ.get('REMEMBER_COOKIE_SECURE', 'false').lower() == 'true'

    ''' # Flask-Mail # '''
    MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
    MAIL_SERVER = os.environ.get('MAIL_SERVER')
    MAIL_PORT = int(os.environ.get('MAIL_PORT'))
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_USE_SSL = os.environ.get('MAIL_USE_SSL', 'false').lower() == 'true'
    MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'false').lower() == 'true'

    ''' # Flask-SQLAlchemy # '''
    SQLALCHEMY_DATABASE_URI = \
        os.environ.get('SQLALCHEMY_DATABASE_URI') \
        or f'sqlite:///{os.path.join(basedir, "data.sqlite")}'
    SQLALCHEMY_RECORD_QUERIES = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False

    ''' # nopaque # '''
    NOPAQUE_ADMIN = os.environ.get('NOPAQUE_ADMIN')
    NOPAQUE_DATA_DIR = \
        os.path.abspath(os.environ.get('NOPAQUE_DATA_DIR', '/mnt/nopaque'))
    NOPAQUE_IS_PRIMARY_INSTANCE = \
        os.environ.get('NOPAQUE_IS_PRIMARY_INSTANCE', 'true').lower() == 'true'
    NOPAQUE_MAIL_SUBJECT_PREFIX = '[nopaque]'
    NOPAQUE_SERVICE_DESK = 'gitlab-ub-incoming+sfb1288inf-nopaque-1324-issue-@jura.uni-bielefeld.de'  # noqa
    NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI = \
        os.environ.get('NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI')

    NOPAQUE_JOB_EXPIRATION_ENABLED = os.environ.get('NOPAQUE_JOB_EXPIRATION_ENABLED', 'true').lower() == 'true'
    NOPAQUE_JOB_EXPIRATION_TIME = int(os.environ.get('NOPAQUE_JOB_EXPIRATION_TIME', '120'))

    NOPAQUE_DOCKER_REGISTRY = 'gitlab.ub.uni-bielefeld.de:4567'
    NOPAQUE_DOCKER_IMAGE_PREFIX = f'{NOPAQUE_DOCKER_REGISTRY}/sfb1288inf/'
    NOPAQUE_DOCKER_REGISTRY_USERNAME = \
        os.environ.get('NOPAQUE_DOCKER_REGISTRY_USERNAME')
    NOPAQUE_DOCKER_REGISTRY_PASSWORD = \
        os.environ.get('NOPAQUE_DOCKER_REGISTRY_PASSWORD')

    NOPAQUE_LOG_DATE_FORMAT = \
        os.environ.get('NOPAQUE_LOG_DATE_FORMAT', '%Y-%m-%d %H:%M:%S')
    NOPAQUE_LOG_FORMAT = os.environ.get(
        'NOPAQUE_LOG_DATE_FORMAT',
        '[%(asctime)s] %(levelname)s in '
        '%(pathname)s (function: %(funcName)s, line: %(lineno)d): %(message)s'
    )
    NOPAQUE_LOG_LEVEL = os.environ.get('NOPAQUE_LOG_LEVEL', 'INFO')
    NOPAQUE_LOG_FILE_ENABLED = \
        os.environ.get('NOPAQUE_LOG_FILE_ENABLED', 'true').lower() == 'true'
    NOPAQUE_LOG_FILE_DIR = \
        os.environ.get('NOPAQUE_LOG_FILE_DIR', os.path.join(basedir, 'logs'))
    NOPAQUE_LOG_FILE_LEVEL = \
        os.environ.get('NOPAQUE_LOG_FILE_LEVEL', NOPAQUE_LOG_LEVEL)
    NOPAQUE_LOG_STDERR_ENABLED = \
        os.environ.get('NOPAQUE_LOG_STDERR_ENABLED', 'false').lower() == 'true'
    NOPAQUE_LOG_STDERR_LEVEL = \
        os.environ.get('NOPAQUE_LOG_STDERR_LEVEL', NOPAQUE_LOG_LEVEL)

    NOPAQUE_PROXY_FIX_ENABLED = \
        os.environ.get('NOPAQUE_PROXY_FIX_ENABLED', 'false').lower() == 'true'
    NOPAQUE_PROXY_FIX_X_FOR = \
        int(os.environ.get('NOPAQUE_PROXY_FIX_X_FOR', '0'))
    NOPAQUE_PROXY_FIX_X_HOST = \
        int(os.environ.get('NOPAQUE_PROXY_FIX_X_HOST', '0'))
    NOPAQUE_PROXY_FIX_X_PORT = \
        int(os.environ.get('NOPAQUE_PROXY_FIX_X_PORT', '0'))
    NOPAQUE_PROXY_FIX_X_PREFIX = \
        int(os.environ.get('NOPAQUE_PROXY_FIX_X_PREFIX', '0'))
    NOPAQUE_PROXY_FIX_X_PROTO = \
        int(os.environ.get('NOPAQUE_PROXY_FIX_X_PROTO', '0'))

    NOPAQUE_TRANSKRIBUS_ENABLED = \
        os.environ.get('NOPAQUE_TRANSKRIBUS_ENABLED', 'false').lower() == 'true'
    NOPAQUE_READCOOP_USERNAME = os.environ.get('NOPAQUE_READCOOP_USERNAME')
    NOPAQUE_READCOOP_PASSWORD = os.environ.get('NOPAQUE_READCOOP_PASSWORD')

    @staticmethod
    def init_app(app: Flask):
        # Set up logging according to the corresponding (NOPAQUE_LOG_*)
        # configurations
        app.logger.setLevel(app.config['NOPAQUE_LOG_LEVEL'])
        # Remove existing handlers
        for handler in app.logger.handlers:
            app.logger.removeHandler(handler)
        # Setup handlers
        formatter = logging.Formatter(
            fmt=app.config['NOPAQUE_LOG_FORMAT'],
            datefmt=app.config['NOPAQUE_LOG_DATE_FORMAT']
        )
        if app.config['NOPAQUE_IS_PRIMARY_INSTANCE']:
           app.config['JOBS'].append(
                {
                    "id": "daemon",
                    "func": "app.daemon:daemon",
                    "args": (app,),
                    "trigger": "interval",
                    "seconds": 3,
                }
           )
        if app.config['NOPAQUE_LOG_STDERR_ENABLED']:
            stream_handler = logging.StreamHandler()
            stream_handler.setFormatter(formatter)
            stream_handler.setLevel(app.config['NOPAQUE_LOG_STDERR_LEVEL'])
            app.logger.addHandler(stream_handler)
        if app.config['NOPAQUE_LOG_FILE_ENABLED']:
            if not os.path.exists(app.config['NOPAQUE_LOG_FILE_DIR']):
                os.mkdir(app.config['NOPAQUE_LOG_FILE_DIR'])
            rotating_file_handler = RotatingFileHandler(
                os.path.join(app.config['NOPAQUE_LOG_FILE_DIR'], 'nopaque.log'),  # noqa
                maxBytes=10_240,
                backupCount=10
            )
            rotating_file_handler.setFormatter(formatter)
            rotating_file_handler.setLevel(app.config['NOPAQUE_LOG_FILE_LEVEL'])  # noqa
            app.logger.addHandler(rotating_file_handler)

        if app.config['NOPAQUE_PROXY_FIX_ENABLED']:
            # Set up and apply the ProxyFix middleware according to the
            # corresponding (NOPAQUE_PROXY_FIX_*) configurations
            app.wsgi_app = ProxyFix(
                app.wsgi_app,
                x_for=app.config['NOPAQUE_PROXY_FIX_X_FOR'],
                x_host=app.config['NOPAQUE_PROXY_FIX_X_HOST'],
                x_port=app.config['NOPAQUE_PROXY_FIX_X_PORT'],
                x_prefix=app.config['NOPAQUE_PROXY_FIX_X_PREFIX'],
                x_proto=app.config['NOPAQUE_PROXY_FIX_X_PROTO']
            )
