#!/usr/bin/env python3

import qarnot
import logging
from logging.config import fileConfig
from airflow import AirflowException
import sys
import time


def configure_logger(path_local_logging_config):
    """ Configure the logger
    """
    try:
        print("Configure logger")
        print("config file = " + path_local_logging_config)
        fileConfig(path_local_logging_config)
        logger = logging.getLogger()
        return(logger)
    except KeyError:
        print("*** Local logging file config has an issue: check path \
              and content")
        raise AirflowException


def qarnot_connection(path_config_qarnot, logger):
    """Start the connection to Qarnot AirflowException
    """
    try:
        conn = qarnot.Connection(path_config_qarnot)
        return(conn)
    except FileNotFoundError:
        logger.exception("Path for Qarnot config is incorrect")
        raise AirflowException


def check_cancellation(task, job, delete_task, logger):
    """Raise an airflow exception if the task was cancelled
    Delete task and job if arg delete_task==True
    """
    if task.state == 'Cancelled':
        logger.warn('Task was aborted, either manually, or job_timeout was '
                    + ' exceeded')

        # delete task and job if delete_task
        if delete_task:
            del_task_job(task, job, logger)

        # The exception returns a non-zero code,
        # hence generating a fail in the airflow pipeline
        raise AirflowException


def check_failure(task, job, delete_task, logger):
    """Raise an airflow exception if the task failed, and print the error
    message.
    Delete task and job if arg delete_task==True
    """
    if task.state == 'Failure':
        logger.error("** Errors: %s" % task.errors[0])

        # delete task and job if delete_task
        if delete_task:
            del_task_job(task, job, logger)

        # The exception returns a non-zero code,
        # hence generating a fail in the airflow pipeline
        raise AirflowException


def handle_error(logger, delete_task, task=None, job=None, waiting_time=10):

    # give a hint if the cause is a job_timeout
    if job.state == "Completed":
        logger.exception("Job timeout aborted the task and job.")
    else:
        logger.exception("Exception occured")

    # If the job is timed out already, download logs and abort the task
    if task is not None:
        if task.state == 'FullyExecuting':
            task.instant()
            task.wait(waiting_time)
            logger.warn("Task abortion")
            task.abort()

        # delete task and job if delete_task
        if delete_task:
            del_task_job(task, job, logger)

    # The exception returns a non-zero code,
    # hence generating a fail in the airflow pipeline
    logger.warn("AirflowException raised")
    raise AirflowException


def insert_in_list(msg, index, *values):
    """ Insert several values in a list, starting from the parameter index
    """
    i = 0
    for v in values:
        msg.insert(index + i, v)
        i += 1


def del_task_job(task, job, logger):
    """ Deletes task and job
    """
    logger.debug("Parameter delete_task set to True")
    logger.debug("Delete task")
    task.delete()

    # wait for the task to be deleted before deleting job
    not_deleted = True
    while not_deleted:
        try:
            if task.state == 'Deleted':
                not_deleted = False
            else:
                time.sleep(2)
        except qarnot.exceptions.MissingTaskException:
            not_deleted = False
    logger.debug("Delete job")
    job.delete(forceAbort=True)
