from flask import render_template, redirect, url_for, flash, Blueprint
from celery import states
from celery.utils.log import get_task_logger
from flask_admin.contrib.sqla import ModelView
from flask_login import login_required

from database import app, admin, db, celery
from flask_covid19.blueprints.app_web.web_dispachter_matrix_service import ecdc_service
from flask_covid19.blueprints.data_ecdc.ecdc_test_service import EcdcTestService

from flask_covid19.blueprints.data_ecdc.ecdc_model_import import EcdcImport, EcdcFlat
from flask_covid19.blueprints.data_ecdc.ecdc_model import EcdcDateReported, EcdcContinent, EcdcCountry, EcdcData
from flask_covid19.blueprints.app_web.web_model_transient import WebPageContent


app_ecdc = Blueprint('ecdc', __name__, template_folder='templates', url_prefix='/ecdc')

admin.add_view(ModelView(EcdcImport, db.session, category="ECDC"))
admin.add_view(ModelView(EcdcFlat, db.session, category="ECDC"))
admin.add_view(ModelView(EcdcDateReported, db.session, category="ECDC"))
admin.add_view(ModelView(EcdcContinent, db.session, category="ECDC"))
admin.add_view(ModelView(EcdcCountry, db.session, category="ECDC"))
admin.add_view(ModelView(EcdcData, db.session, category="ECDC"))


# ---------------------------------------------------------------------------------------------------------------
#  Url Routes Frontend
# ---------------------------------------------------------------------------------------------------------------

@app_ecdc.route('/info')
def url_ecdc_info():
    page_info = WebPageContent('Europe', "Info")
    return render_template(
        'ecdc/ecdc_info.html',
        title='Europe',
        page_info=page_info)


@app_ecdc.route('/tasks')
def url_ecdc_tasks():
    page_info = WebPageContent('Europe', "Tasks")
    return render_template(
        'ecdc/ecdc_tasks.html',
        title='Europe Tasks',
        page_info=page_info)


@app_ecdc.route('/imported/page/<int:page>')
@app_ecdc.route('/imported')
def url_ecdc_data_imported(page=1):
    page_info = WebPageContent('Europe', "Last Import")
    page_data = EcdcImport.get_all_as_page(page)
    return render_template(
        'ecdc/imported/ecdc_imported.html',
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/date_reported/all/page/<int:page>')
@app_ecdc.route('/date_reported/all')
def url_ecdc_date_reported_all(page=1):
    page_info = WebPageContent('Europe', "date_reported")
    page_data = EcdcDateReported.get_all_as_page(page)
    return render_template(
        'ecdc/date_reported/ecdc_date_reported_all.html',
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/date_reported/<int:europe_date_reported_id>/page/<int:page>')
@app_ecdc.route('/date_reported/<int:europe_date_reported_id>')
@app_ecdc.route('/date_reported/notification_rate/<int:europe_date_reported_id>/page/<int:page>')
@app_ecdc.route('/date_reported/notification_rate/<int:europe_date_reported_id>')
def url_ecdc_date_reported_one_notification_rate(europe_date_reported_id, page=1):
    page_info = WebPageContent('Europe', "date_reported")
    europe_date_reported = EcdcDateReported.get_by_id(europe_date_reported_id)
    page_data = EcdcData.find_by_date_reported_notification_rate(europe_date_reported, page)
    return render_template(
        'ecdc/date_reported/ecdc_date_reported_one_notification_rate.html',
        europe_date_reported=europe_date_reported,
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/date_reported/deaths_weekly/<int:europe_date_reported_id>/page/<int:page>')
@app_ecdc.route('/date_reported/deaths_weekly/<int:europe_date_reported_id>')
def url_ecdc_date_reported_one_deaths_weekly(europe_date_reported_id, page=1):
    page_info = WebPageContent('Europe', "date_reported")
    europe_date_reported = EcdcDateReported.get_by_id(europe_date_reported_id)
    page_data = EcdcData.find_by_date_reported_deaths_weekly(europe_date_reported, page)
    return render_template(
        'ecdc/date_reported/ecdc_date_reported_one_deaths_weekly.html',
        europe_date_reported=europe_date_reported,
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/date_reported/cases_weekly/<int:europe_date_reported_id>/page/<int:page>')
@app_ecdc.route('/date_reported/cases_weekly/<int:europe_date_reported_id>')
def url_ecdc_date_reported_one_cases_weekly(europe_date_reported_id, page=1):
    page_info = WebPageContent('Europe', "date_reported")
    europe_date_reported = EcdcDateReported.get_by_id(europe_date_reported_id)
    page_data = EcdcData.find_by_date_reported_cases_weekly(europe_date_reported, page)
    return render_template(
        'ecdc/date_reported/ecdc_date_reported_one_cases_weekly.html',
        europe_date_reported=europe_date_reported,
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/continent/all/page/<int:page>')
@app_ecdc.route('/continent/all')
def url_ecdc_continent_all(page=1):
    page_info = WebPageContent('Europe', "continent")
    page_data = EcdcContinent.get_all_as_page(page)
    return render_template(
        'ecdc/continent/ecdc_continent_all.html',
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/continent/<int:continent_id>/page/<int:page>')
@app_ecdc.route('/continent/<int:continent_id>')
def url_ecdc_continent_one(continent_id, page=1):
    page_info = WebPageContent('Europe', "continent")
    continent = EcdcContinent.get_by_id(continent_id)
    page_data = EcdcCountry.find_by_continent(continent, page)
    return render_template(
        'ecdc/continent/ecdc_continent_one.html',
        continent=continent,
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/country/all/page/<int:page>')
@app_ecdc.route('/country/all')
def url_ecdc_country_all(page=1):
    page_info = WebPageContent('Europe', "country")
    page_data = EcdcCountry.get_all_as_page(page)
    return render_template(
        'ecdc/country/ecdc_country_all.html',
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/country/<int:country_id>/page/<int:page>')
@app_ecdc.route('/country/<int:country_id>')
def url_ecdc_country_one(country_id, page=1):
    page_info = WebPageContent('Europe', "country")
    europe_country = EcdcCountry.get_by_id(country_id)
    page_data = EcdcData.find_by_country(europe_country, page)
    return render_template(
        'ecdc/country/ecdc_country_one.html',
        europe_country=europe_country,
        page_data=page_data,
        page_info=page_info)


@app_ecdc.route('/country/germany/page/<int:page>')
@app_ecdc.route('/country/germany')
def url_ecdc_country_germany(page=1):
    page_info = WebPageContent('Europe', "country: Germany")
    europe_country = EcdcCountry.get_germany()
    if europe_country is None:
        flash('country: Germany not found in Database', category='error')
        return redirect(url_for('ecdc.url_ecdc_tasks'))
    page_data = EcdcData.find_by_country(europe_country, page)
    return render_template(
        'ecdc/country/ecdc_country_germany.html',
        europe_country=europe_country,
        page_data=page_data,
        page_info=page_info)


# ----------------------------------------------------------------------------------------------------------------
#  Celery TASKS
# ----------------------------------------------------------------------------------------------------------------


@celery.task(bind=True)
def task_ecdc_import(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_import [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.import_file()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_import)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update_dimension_tables(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update_dimension_tables [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update_dimension_tables()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_full_update_dimension_tables)"
    return result


@celery.task(bind=True)
def task_ecdc_update_dimension_tables(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_update_dimension_tables [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.update_dimension_tables()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_update_dimension_tables)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update_fact_table(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update_fact_table [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update_fact_table()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_full_update_fact_table)"
    return result


@celery.task(bind=True)
def task_ecdc_update_fact_table(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_update_fact_table [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.update_fact_table()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_update_fact_table)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update_fact_table(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update_fact_table [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update_fact_table()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_full_update_fact_table)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update_star_schema(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update_star_schema [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update_star_schema()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_update_star_schema_incremental)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update_star_schema(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update_star_schema [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update_star_schema()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_full_update_star_schema)"
    return result


@celery.task(bind=True)
def task_ecdc_update_star_schema(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_update_star_schema [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.update_star_schema()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_update_star_schema)"
    return result


@celery.task(bind=True)
def task_ecdc_full_update(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_full_update [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.full_update()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_full_update)"
    return result


@celery.task(bind=True)
def task_ecdc_update(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_update [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_service.update()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_update)"
    return result


# ----------------------------------------------------------------------------------------------------------------
#  URL Routes for Celery TASKS
# ----------------------------------------------------------------------------------------------------------------


@app_ecdc.route('/task/download')
def url_ecdc_task_download():
    app.logger.info("url_ecdc_task_download [start]")
    ecdc_service.download()
    flash("ecdc_service.download done")
    app.logger.info("url_ecdc_task_download [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/import')
def url_ecdc_task_import():
    app.logger.info("url_ecdc_task_import [start]")
    task_ecdc_import.apply_async()
    flash("task_ecdc_import started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_ecdc_task_import [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/update/dimension-tables')
def url_ecdc_task_update_dimension_tables():
    app.logger.info("url_ecdc_task_update_dimension_tables [start]")
    task_ecdc_update_dimension_tables.apply_async()
    flash("task_ecdc_update_dimension_tables started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_ecdc_task_update_dimension_tables [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/full/update/dimension-tables')
def url_ecdc_task_full_update_dimension_tables():
    app.logger.info("url_ecdc_task_full_update_dimension_tables [start]")
    task_ecdc_full_update_dimension_tables.apply_async()
    flash("url_ecdc_task_full_update_dimensiontables started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_ecdc_task_full_update_dimension_tables [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/full/update/fact-table')
def url_task_ecdc_full_update_fact_table():
    app.logger.info("url_task_ecdc_full_update_fact_table [start]")
    task_ecdc_full_update_fact_table.apply_async()
    flash("task_ecdc_full_update_fact_table started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_full_update_fact_table [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/update/fact-table')
def url_task_ecdc_update_fact_table():
    app.logger.info("url_task_ecdc_update_fact_table [start]")
    task_ecdc_update_fact_table.apply_async()
    flash("task_ecdc_update_fact_table started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_update_fact_table [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/full/update/star_schema')
def url_task_ecdc_full_update_star_schema():
    app.logger.info("url_task_ecdc_full_update_star_schema [start]")
    task_ecdc_full_update_star_schema.apply_async()
    flash("url_ecdc_task_full_update_star_schema started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_full_update_star_schema [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/update/star_schema')
def url_task_ecdc_update_star_schema():
    app.logger.info("url_task_ecdc_update_star_schema [start]")
    task_ecdc_update_star_schema.apply_async()
    flash("url_ecdc_task_full_update_star_schema started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_update_star_schema [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/full/update')
def url_task_ecdc_full_update():
    app.logger.info("url_task_ecdc_full_update [start]")
    ecdc_service.download()
    flash("ecdc_service.download done")
    task_ecdc_full_update.apply_async()
    flash("task_ecdc_full_update started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_full_update [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


@app_ecdc.route('/task/update')
def url_task_ecdc_update():
    app.logger.info("url_task_ecdc_update [start]")
    ecdc_service.download()
    flash("ecdc_service.download done")
    task_ecdc_update.apply_async()
    flash("task_ecdc_update started")
    flash(message="long running background task started", category="warning")
    app.logger.info("url_task_ecdc_update [done]")
    return redirect(url_for('ecdc.url_ecdc_tasks'))


ecdc_test_service = EcdcTestService(db, ecdc_service)


# ---------------------------------------------------------------------------------------------------------------
#  Url Routes Frontend  TEST
# ---------------------------------------------------------------------------------------------------------------


@app_ecdc.route('/test/tests')
@login_required
def url_ecdc_test_tests():
    page_info = WebPageContent('ECDC', "Tests")
    return render_template(
        'ecdc_test/templates/ecdc/ecdc_tests.html',
        page_info=page_info)


@app_ecdc.route('/test/ecdc_import/countries')
@login_required
def url_ecdc_test_ecdc_import_countries():
    flash("url_ecdc_test_ecdc_import_countries - START: EcdcImport.countries()")
    app.logger.info("url_ecdc_test_ecdc_import_countries - START: EcdcImport.countries()")
    i = 0
    for c in EcdcImport.countries():
        i += 1
        line = " | " + str(i) + " | " + c.countries.country_code + " | " + c.countries.country + " | " + c.countries.ecdc_region + " | "
        app.logger.info(line)
    flash("url_ecdc_test_ecdc_import_countries - DONE: EcdcImport.countries()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


@app_ecdc.route('/test/ecdc_import/get_new_dates_as_array')
@login_required
def url_ecdc_test_ecdc_import_get_new_dates_as_array():
    app.logger.info("url_ecdc_mytest - DONE: EcdcImport.countries()")
    flash("url_ecdc_mytest - START: EcdcImport.get_new_dates_as_array()")
    app.logger.info("url_ecdc_mytest - START: EcdcImport.get_new_dates_as_array()")
    app.logger.info("EcdcImport.get_new_dates_as_array():")
    i = 0
    for date_reported in EcdcImport.get_new_dates_as_array():
        i += 1
        line = " | " + str(i) + " | " + date_reported + " | "
        app.logger.info(line)
    flash("url_ecdc_mytest - DONE: EcdcImport.get_new_dates_as_array()")
    app.logger.info("url_ecdc_mytest - DONE: EcdcImport.get_new_dates_as_array()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


@app_ecdc.route('/test/ecdc_data/get_datum_of_all_ecdc_data')
@login_required
def url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_data():
    app.logger.info("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_data - DONE: EcdcData.get_datum_of_all_ecdc_data()")
    flash("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_data - START: EcdcData.get_datum_of_all_ecdc_data()")
    for datum in EcdcImport.get_datum_of_all_data():
        app.logger.info(str(datum))
    flash("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_data - DONE: EcdcData.get_datum_of_all_ecdc_data()")
    app.logger.info("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_data - DONE: EcdcData.get_datum_of_all_ecdc_data()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


@app_ecdc.route('/test/ecdc_data/get_datum_of_all_ecdc_import')
@login_required
def url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_import():
    app.logger.info("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_import - START: EcdcImport.get_datum_of_all_ecdc_import()")
    flash("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_import - START: EcdcImport.get_datum_of_all_ecdc_import()")
    for datum in EcdcImport.get_datum_of_all_ecdc_import():
        app.logger.info(str(datum))
    flash("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_import - DONE: EcdcImport.get_datum_of_all_ecdc_import()")
    app.logger.info("url_ecdc_test_ecdc_data_get_datum_of_all_ecdc_import - DONE: EcdcImport.get_datum_of_all_ecdc_import()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


@app_ecdc.route('/test/ecdc_service/service_update/ecdc_import_get_new_dates_as_array')
@login_required
def url_ecdc_test_ecdc_service_ecdc_import_get_new_dates_as_array():
    app.logger.info("url_ecdc_test_ecdc_import_get_new_dates_as_array - START: EcdcService.ecdc_import_get_new_dates_as_array()")
    flash("url_ecdc_test_ecdc_import_get_new_dates_as_array - START: EcdcService.ecdc_import_get_new_dates_as_array()")
    for datum in ecdc_service.service_update.ecdc_import_get_new_dates_as_array():
        app.logger.info(str(datum))
    flash("url_ecdc_test_ecdc_import_get_new_dates_as_array - DONE: EcdcService.ecdc_import_get_new_dates_as_array()")
    app.logger.info("url_ecdc_test_ecdc_import_get_new_dates_as_array - DONE: EcdcService.ecdc_import_get_new_dates_as_array()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


@app_ecdc.route('/test/ecdc_test_service/delete_last_day')
@login_required
def url_ecdc_test_ecdc_test_service_delete_last_days_data():
    app.logger.info("url_ecdc_test_ecdc_test_service_delete_last_days_data - START: EcdcService.ecdc_import_get_new_dates_as_array()")
    flash("url_ecdc_test_ecdc_test_service_delete_last_days_data - START: EcdcService.ecdc_import_get_new_dates_as_array()")
    ecdc_test_service.delete_last_day()
    flash("url_ecdc_test_ecdc_test_service_delete_last_days_data - DONE: EcdcService.ecdc_import_get_new_dates_as_array()")
    app.logger.info("url_ecdc_test_ecdc_test_service_delete_last_days_data - DONE: EcdcService.ecdc_import_get_new_dates_as_array()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))


# ----------------------------------------------------------------------------------------------------------------
#  Celery TASKS
# ----------------------------------------------------------------------------------------------------------------


@celery.task(bind=True)
def task_ecdc_test_update_star_schema_incremental(self):
    logger = get_task_logger(__name__)
    self.update_state(state=states.STARTED)
    logger.info("------------------------------------------------------------")
    logger.info(" Received: task_ecdc_test_update_star_schema_incremental [OK] ")
    logger.info("------------------------------------------------------------")
    ecdc_test_service.run_update_star_schema_incremental()
    self.update_state(state=states.SUCCESS)
    result = "OK (task_ecdc_test_update_star_schema_incremental)"
    return result

# ----------------------------------------------------------------------------------------------------------------
#  URL Routes for Celery TASKS
# ----------------------------------------------------------------------------------------------------------------


@app_ecdc.route('/test/task/update_star_schema_incremental')
@login_required
def url_task_ecdc_test_update_star_schema_incremental():
    app.logger.info("url_task_ecdc_test_update_star_schema_incremental - START: task_ecdc_test_update_star_schema_incremental()")
    flash("url_task_ecdc_test_update_star_schema_incremental - START: task_ecdc_test_update_star_schema_incremental()")
    task_ecdc_test_update_star_schema_incremental.apply_async()
    flash("url_task_ecdc_test_update_star_schema_incremental - DONE: task_ecdc_test_update_star_schema_incremental()")
    app.logger.info("url_task_ecdc_test_update_star_schema_incremental - DONE: task_ecdc_test_update_star_schema_incremental()")
    return redirect(url_for('ecdc_test.url_ecdc_test_tests'))