#!/usr/bin/env python3

import os
import json
import argparse
import logging

from kombu import Connection, Exchange, Queue, Consumer, eventloop
import yaml

from git_slack import slack, response

logger = logging.getLogger(__name__)


if __name__ == '__main__':
    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description='Post Git push information from AMQP to Slack')
    parser.add_argument('--config', metavar='file',
                        help='Configuration file')
    args = parser.parse_args()

    logging.basicConfig(level=logging.INFO)

    # Load configuration file
    if args.config:
        with open(args.config, 'r') as f:
            config = yaml.load(f)
    else:
        config = {}

    server_host = os.environ.get('AMQP_PORT_5672_TCP_ADDR', 'localhost')
    server_port = int(os.environ.get('AMQP_PORT_5672_TCP_PORT', '5672'))
    server_address = 'amqp://{}:{}'.format(server_host, server_port)

    # Run Slack WebHook connector
    if 'slack' in config and 'webhook_url' in config['slack']:
        logger.info('Using Slack WebHook URL: {}'.format(
            config['slack']['webhook_url']))
        hook = slack.SlackWebHook(config['slack']['webhook_url'])
        hook.start()
    else:
        logger.warning('No Slack URL defined! No messages will be sent.')
        logger.warning('Set "slack.webhook_url" in the configuration' +
                       ' file to enable Slack messages.')
        hook = None

    # Define Slack message options
    slack_username = None
    slack_channel = None
    if 'slack' in config:
        if 'username' in config['slack']:
            slack_username = str(config['slack']['username'])
        if 'channel' in config['slack']:
            slack_channel = str(config['slack']['channel'])

    # Define routing/filtering rules
    rules = config.get('rules', [])

    # Declare AMQP exchange and queue
    git_exchange = Exchange('git', type='topic', durable=False)
    queue = Queue(exchange=git_exchange, routing_key='#',
                  exclusive=True)

    # Callback on Git push messages
    def callback(body, message):
        try:
            for push, username, channel in response.apply_rules(
                    body, rules, slack_username, slack_channel):
                slack_message = response.message_from_push(
                    push, username, channel)
                if slack_message is not None and hook is not None:
                    hook.enqueue(slack_message)
        except:
            logger.warning('Unable to process push:', exc_info=True)

        message.ack()

    logger.info("Waiting for Git push messages...")

    with Connection(server_address) as connection:
        with Consumer(connection, queue, accept=['json'],
                      callbacks=[callback]):
            try:
                for _ in eventloop(connection, timeout=1, ignore_timeouts=True):
                    pass
            except KeyboardInterrupt:
                pass
            finally:
                if hook is not None:
                    logger.info('Stopping Slack WebHook connector...')
                    hook.stop()

        logger.info('Closing AMQP connection...')

    logger.info('Done.')
