""" Initialize the package. """

import os
import configparser
import logging
import logging.config

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import SQLAlchemyError
import yaml

from asl_articles.config.constants import BASE_DIR
from asl_articles.utils import to_bool

_disable_db_startup = False

# ---------------------------------------------------------------------

def _on_startup():
    """Do startup initialization."""

    if not _disable_db_startup:

        # check if we have a working database connection
        if _dbconn_string.startswith( "sqlite:///" ):
            # NOTE: If the SQLite database is not there, a zero-byte file will be created the first time
            # we try to use it, so we can't use the normal check we use below for other databases.
            # NOTE: We could automatically set up a new database file and install the schema into it,
            # but that's probably more trouble than it's worth, and possibly a cause of problems in itself :-/
            fname = _dbconn_string[10:]
            if not os.path.isfile( fname ):
                asl_articles.startup.log_startup_msg( "error", "Missing SQLite database:\n{}", fname )
                return
        else:
            try:
                db.session.execute( "SELECT 1" )
            except SQLAlchemyError as ex:
                asl_articles.startup.log_startup_msg( "error", "Can't connect to the database:\n{}", ex )
                return

        # initialize the search index
        logger = logging.getLogger( "startup" )
        asl_articles.search.init_search( db.session, logger )

# ---------------------------------------------------------------------

def _load_config( cfg, fname, section ):
    """Load config settings from a file."""
    if not os.path.isfile( fname ):
        return
    config_parser = configparser.ConfigParser()
    config_parser.optionxform = str # preserve case for the keys :-/
    config_parser.read( fname )
    cfg.update( dict( config_parser.items( section ) ) )

# ---------------------------------------------------------------------

# initialize
_cfg = {}

# load the application configuration
config_dir = os.path.join( BASE_DIR, "config" )
_fname = os.path.join( config_dir, "app.cfg" )
_load_config( _cfg, _fname, "System" )

# load any site configuration
_fname = os.path.join( config_dir, "site.cfg" )
_load_config( _cfg, _fname, "Site Config" )

# load any debug configuration
_fname = os.path.join( config_dir, "debug.cfg" )
_load_config( _cfg, _fname, "Debug" )

# initialize logging
_fname = os.path.join( config_dir, "logging.yaml" )
if os.path.isfile( _fname ):
    with open( _fname, "r", encoding="utf-8" ) as fp:
        logging.config.dictConfig( yaml.safe_load( fp ) )
else:
    # stop Flask from logging every request :-/
    logging.getLogger( "werkzeug" ).setLevel( logging.WARNING )

# initialize Flask
base_dir = os.path.join( BASE_DIR, ".." )
app = Flask( __name__ )
app.config.update( _cfg )

# initialize the database connection
app.config[ "_IS_CONTAINER" ] = _cfg.get( "IS_CONTAINER" )
if _cfg.get( "IS_CONTAINER" ):
    # if we are running in a container, the database must be specified in an env variable e.g.
    #   docker run -e DBCONN=...
    _dbconn_string = os.environ.get( "DBCONN" )
else:
    _dbconn_string = app.config.get( "DB_CONN_STRING" )
app.config[ "SQLALCHEMY_DATABASE_URI" ] = _dbconn_string
app.config[ "SQLALCHEMY_TRACK_MODIFICATIONS" ] = False
app.config[ "SQLALCHEMY_ECHO" ] = to_bool( app.config.get( "SQLALCHEMY_ECHO" ) )
db = SQLAlchemy( app )

# load the application
import asl_articles.globvars #pylint: disable=cyclic-import
import asl_articles.startup #pylint: disable=cyclic-import
import asl_articles.main #pylint: disable=cyclic-import
import asl_articles.search #pylint: disable=cyclic-import
import asl_articles.publishers #pylint: disable=cyclic-import
import asl_articles.publications #pylint: disable=cyclic-import
import asl_articles.articles #pylint: disable=cyclic-import
import asl_articles.authors #pylint: disable=cyclic-import
import asl_articles.scenarios #pylint: disable=cyclic-import
import asl_articles.images #pylint: disable=cyclic-import
import asl_articles.tags #pylint: disable=cyclic-import
import asl_articles.docs #pylint: disable=cyclic-import
import asl_articles.db_report #pylint: disable=cyclic-import
import asl_articles.utils #pylint: disable=cyclic-import

# initialize
asl_articles.utils.load_html_whitelists( app )

# register startup initialization
app.before_first_request( _on_startup )
