# By: Riasat Ullah
# This file handles notices that are send to th app.

from requests.exceptions import ConnectionError
from requests.exceptions import HTTPError
from threading import Thread
from utils.expo_push_notifications import PushClient, PushMessage, PushServerError
from utils import constants, logging, times, var_names


def send_notice(messages):
    '''
    Send push notifications to a user's phone.
    :param messages: (list) of dict of messages {push_token: ..., message_body: ..., extra_data: ...,}
    :errors: PushServerError, PushResponseError, ConnectionError, HttpError, DeviceNotRegisteredError
    '''
    try:
        push_messages = []
        for item in messages:
            msg = PushMessage(to=item[var_names.push_token], title=item[var_names.notice_title],
                              body=item[var_names.message], data=item[var_names.extra_data],
                              priority='high', sound='default',
                              interruption_level='critical'
                              if var_names.is_critical in item and item[var_names.is_critical] else 'active')
            push_messages.append(msg)
        responses = PushClient().publish_multiple(push_messages)
        for item in responses:
            if item.status == 'ok':
                logging.info('Expo push notification ID: ' + str(item.id))
            else:
                logging.error('Expo push notification instruction failed')
                logging.error(item)
    except PushServerError as e:
        # Encountered some likely formatting/validation error.
        logging.exception(str(e))
        raise PushServerError
    except (ConnectionError, HTTPError) as e:
        # Encountered some Connection or HTTP error - retry a few times in
        # case it is transient.
        logging.exception(str(e))
        raise IOError(str(e))

    # try:
    #     # We got a response back, but we don't know whether it's an error yet.
    #     # This call raises errors so we can handle them with normal exception
    #     # flows.
    #     responses.validate_response()
    # except DeviceNotRegisteredError as e:
    #     # Mark the push token as inactive
    #     logging.exception(str(e))
    #     raise Exception(e)
    # except PushResponseError as e:
    #     # Encountered some other per-notification error.
    #     logging.exception(str(e))
    #     raise PushResponseError(e)


class NoticeSender(Thread):
    '''
    Sends push notification, but runs as a thread.
    '''
    def __init__(self, messages):
        self.messages = messages
        Thread.__init__(self, name='NoticeSender_' + times.get_current_timestamp().strftime(constants.timestamp_format))

    def run(self):
        logging.info(self.name + ' - Running notice sender..')
        try:
            send_notice(self.messages)
        except Exception as e:
            logging.exception(str(e))
            logging.warning('Not raising the exception. Passing it through...')
            pass
