"""Lambda handler triggered from events Kinesis stream.

Adds requests to ingest stats about GitHub commits.
"""

import json
import logging
import sys
import urlparse

# Work around problem with lambda and code.justin.tv namespace.
if 'code' in sys.modules:
    del sys.modules['code']
from code.justin.tv.dta.rockpaperscissors import environment
from code.justin.tv.dta.rockpaperscissors import event_bus
from code.justin.tv.dta.rockpaperscissors import errors
from code.justin.tv.dta.rockpaperscissors import ingest_queue


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.getLogger('boto3').setLevel(logging.WARNING)
logging.getLogger('botocore').setLevel(logging.WARNING)


def lambda_handler(event, context):
    env = environment.GetEnvironment(context)
    queue = env.IngestQueue()

    pushed_commits = ProcessRecords(event['Records'])
    requests = MakeRequests(pushed_commits)
    try:
        queue.AddRequests(requests)
    except errors.IngestQueueAddRequestsFailures as e:
        pass


def ProcessRecord(record):
    """Returns generator of (repo_host, repo_name, commit_sha) tuples."""
    try:
        event = event_bus.DecodeKinesisRecordData(record['kinesis']['data'])
    except (errors.EventDecodeError, errors.EventInvalid) as e:
        logger.error(e)
        return

    if event.type != 'GitHub-push':
        return

    github_event = json.loads(event.body)

    # We only care about changes on the "default branch".
    default_branch_ref = (
      'refs/heads/%s' % github_event['repository']['default_branch'])
    if github_event['ref'] != default_branch_ref:
        return

    repo_host = urlparse.urlsplit(github_event['repository']['url']).netloc
    repo_name = github_event['repository']['full_name']
    for commit in github_event['commits']:
        if commit['distinct']:  # "distinct" means hasn't already been pushed
            yield (repo_host, repo_name, commit['id'])


def ProcessRecords(records):
    """Returns generator of (repo_host, repo_name, commit_sha) tuples."""
    logger.info('Processing %d records', len(records))
    for record in records:
        for pushed_commit in ProcessRecord(record):
            yield pushed_commit


def MakeRequests(pushed_commits):
    """Generate protos from (repo_host, repo_name, commit_sha) tuples."""
    for repo_host, repo_name, commit_sha in pushed_commits:
        yield ingest_queue.IngestGitHubStatsRequest(
          github_host=repo_host,
          github_repository=repo_name,
          commit_sha=commit_sha)
