# By: Riasat Ullah
# This file contains functions to handle email triggered alerts.

import sys
sys.path.append('/home/ubuntu/taskcallrest/')

from data_syncers import syncer_checks, syncer_email_assignees
from exceptions.user_exceptions import InvalidRequest, NoOneIsOnCall
from modules.router import Router
from objects.check import Check
from objects.task_payload import TaskPayload
from utils import constants, errors, logging, mail, times, var_names
from utils.db_connection import CACHE_CLIENT, CONN_POOL
import configuration
import email


def create_task_from_email(email_message, conn=None, cache=None):
    '''
    Create a task from an email triggered alert.
    :param email_message: email message
    :param conn: db connection
    :param cache: cache client
    :errors: AssertionError, DatabaseError, ValueError
    '''
    email_from, email_to, title, description = mail.parse_task_from_email(email_message)
    task_timestamp = times.get_current_timestamp()

    # The sender and the recipients email addresses must be from the same organization if the recipients' email.
    # addresses do not have public access. Otherwise, the sender can be anyone with or without a TaskCall account.
    try:
        conn = CONN_POOL.get_db_conn() if conn is None else conn
        cache = CACHE_CLIENT if cache is None else cache

        # Verifies if the email is for a heartbeat check or not. If it is then logs the incoming ping.
        # Otherwise, creates an incident.
        check_ref_id = Check.extract_check_ref_id_from_ping_email_address(email_to)
        if check_ref_id is None:
            email_details = syncer_email_assignees.get_email_assignee_details(conn, cache, task_timestamp, email_to)
            org_id = None
            serv_id = None
            email_pol_ids = []
            if len(email_details) > 0:
                for key in email_details:
                    item = email_details[key]
                    if org_id is None:
                        org_id = item[0]

                    if serv_id is None and item[2] is not None:
                        serv_id = item[2]

                    email_pol_ids.append(item[1])
            else:
                raise InvalidRequest(errors.err_unknown_resource)

            source_payload = {
                var_names.email_from: email_from,
                var_names.email_to: email_to,
                var_names.email_subject: title,
                var_names.email_body: description
            }
            payload = TaskPayload(task_timestamp, org_id, task_timestamp.date(), title, configuration.standard_timezone,
                                  task_timestamp.time(), text_msg=description, urgency_level=constants.high_urgency,
                                  trigger_method=constants.email, trigger_info=source_payload, service_id=serv_id,
                                  assignees=email_pol_ids if len(email_pol_ids) > 0 else None)
            Router(conn, cache, payload).start()
        else:
            syncer_checks.log_heartbeat(conn, cache, task_timestamp, check_ref_id,
                                        constants.email, sender_email=email_from)
    except (InvalidRequest, LookupError, PermissionError, SystemError):
        raise
    finally:
        CONN_POOL.put_db_conn(conn)


if __name__ == '__main__':
    msg = email.message_from_file(sys.stdin)
    try:
        create_task_from_email(msg)
    except InvalidRequest as e:
        logging.exception(str(e))
    except NoOneIsOnCall as e:
        logging.exception(str(e))
    except Exception as e:
        logging.exception(str(e))
