import os
import secrets
import logging
import time
import sys
import json

from flask import Flask, Blueprint
from flask_cors import CORS
from flask_restx import Api, Resource

from threading import Thread

# add dir to python path
sys.path.append("./modules/domain_evaluation_ai/")

# module needs to be imported after path is added
from Core import Net

from modules.Config import Config
from modules.APIClient import APIClient
from modules.ArielSearcher import ArielSearcher
from modules.ClassifierWrapper import ClassifierWrapper

from api.apiConfig import api
from database import db

from api.endpoints.loading import ns as loading_namespace
from api.endpoints.resolution import ns as resolution_namespace
from api.endpoints.analysis import ns as analysis_namespace
from api.endpoints.domain import ns as domain_namespace


from modules.QLoader import QLoader
from modules.DataResolver import DataResolver
from modules.Analyzer import Analyzer

logger = logging.getLogger('domainradar')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler(sys.stdout))

app=Flask(__name__)

def configure_app(flask_app):
    flask_app.config['SECRET_KEY'] = secrets.token_hex(16)
    flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    flask_app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///domainradar.db'

    # DomainRadar-specific objects
    dr_config = Config("config.ini")
    dr_qradar_api_client = APIClient(dr_config)
    dr_ariel_searcher = ArielSearcher(dr_config, dr_qradar_api_client)
    dr_classifier_wrapper = ClassifierWrapper()

    flask_app.config['DR'] = dict()
    flask_app.config['DR']['CONFIG'] = dr_config
    flask_app.config['DR']['QRADAR_API_CLIENT'] = dr_qradar_api_client
    flask_app.config['DR']['ARIEL_SEARCHER'] = dr_ariel_searcher
    flask_app.config['DR']['CLASSIFIER_WRAPPER'] = dr_classifier_wrapper

    flask_app.config['DR']['DAEMON_CONTROL'] = {
        'QLOADER_LOAD': False,
    }

    # Configure the QLoader Daemon
    flask_app.config['DR']['QLOADER'] = QLoader(flask_app)
    flask_app.config['DR']['QLOADER'].thread = Thread(target=app.config['DR']['QLOADER'].mainLoop)
    flask_app.config['DR']['QLOADER'].thread.daemon = True

    # Configurethe DataResolver Daemon
    flask_app.config['DR']['DATARESOLVER'] = DataResolver(flask_app)
    flask_app.config['DR']['DATARESOLVER'].thread = Thread(target=app.config['DR']['DATARESOLVER'].mainLoop)
    flask_app.config['DR']['DATARESOLVER'].thread.daemon = True

    # Configurethe Analyzer Daemon
    flask_app.config['DR']['ANALYZER'] = Analyzer(flask_app)
    flask_app.config['DR']['ANALYZER'].thread = Thread(target=app.config['DR']['ANALYZER'].mainLoop)
    flask_app.config['DR']['ANALYZER'].thread.daemon = True


def initialize_app(flask_app):
    configure_app(flask_app)

    blueprint = Blueprint('api',  __name__)
    api.init_app(blueprint)
    api.add_namespace(loading_namespace)
    api.add_namespace(resolution_namespace)
    api.add_namespace(analysis_namespace)
    api.add_namespace(domain_namespace)

    flask_app.register_blueprint(blueprint)

    CORS(app, supports_credentials=True)
    return flask_app


def main():
    app.config['DR']['QLOADER'].thread.start()
    app.config['DR']['DATARESOLVER'].thread.start()
    app.config['DR']['ANALYZER'].thread.start()
    app.run(host='127.0.0.1', port=5000, threaded=False, debug=True, use_reloader=False)

initialize_app(app)

db.init_app(app)

with app.app_context():
    db.create_all()

if __name__ == "__main__":
    main()
