#!/usr/bin/python

import argparse
import json
import operator
import re
import sys
import subprocess
import time
import urllib
import urllib2

from datetime import datetime
from xml.dom.minidom import parseString as parseXmlString
from util import submit_commits
from util import text_content
from util import load_server_config


def main(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('--os-config-json', required=True, help='The path to a JSON that specifies how to fetch OS build information')
    parser.add_argument('--server-config-json', required=True, help='The path to a JSON file that specifies the perf dashboard')
    parser.add_argument('--seconds-to-sleep', type=float, default=43200, help='The seconds to sleep between iterations')
    args = parser.parse_args()

    with open(args.os_config_json) as os_config_json:
        os_config_list = json.load(os_config_json)

    fetchers = [OSBuildFetcher(os_config) for os_config in os_config_list]

    while True:
        server_config = load_server_config(args.server_config_json)
        for fetcher in fetchers:
            fetcher.fetch_and_report_new_builds(server_config)
        print "Sleeping for %d seconds" % args.seconds_to_sleep
        time.sleep(args.seconds_to_sleep)


# FIXME: Move other static functions into this class.
class OSBuildFetcher:
    def __init__(self, os_config):
        self._os_config = os_config
        self._reported_revisions = set()

    def _fetch_available_builds(self):
        config = self._os_config
        repository_name = self._os_config['name']

        if 'customCommands' in config:
            available_builds = []
            for command in config['customCommands']:
                print "Executing", ' '.join(command['command'])
                available_builds += available_builds_from_command(repository_name, command['command'], command['linesToIgnore'])
        else:
            url = config['buildSourceURL']
            print "Fetching available builds from", url
            available_builds = fetch_available_builds(repository_name, url, config['trainVersionMap'])
        return available_builds

    def fetch_and_report_new_builds(self, server_config):
        available_builds = self._fetch_available_builds()
        reported_revisions = self._reported_revisions
        print 'Found %d builds' % len(available_builds)

        available_builds = filter(lambda commit: commit['revision'] not in reported_revisions, available_builds)
        self._assign_order(available_builds)

        print "Submitting %d builds" % len(available_builds)
        submit_commits(available_builds, server_config['server']['url'], server_config['worker']['name'], server_config['worker']['password'])
        reported_revisions |= set(map(lambda commit: commit['revision'], available_builds))

    @staticmethod
    def _assign_order(builds):
        build_name_regex = re.compile(r'(?P<major>\d+)(?P<kind>\w)(?P<minor>\d+)(?P<variant>\w*)')
        for commit in builds:
            match = build_name_regex.search(commit['revision'])
            major = int(match.group('major'))
            kind = ord(match.group('kind').upper()) - ord('A')
            minor = int(match.group('minor'))
            variant = ord(match.group('variant').upper()) - ord('A') + 1 if match.group('variant') else 0
            commit['order'] = ((major * 100 + kind) * 10000 + minor) * 100 + variant


def available_builds_from_command(repository_name, command, lines_to_ignore):
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as error:
        print "Failed:", str(error)
        return []

    regex = re.compile(lines_to_ignore)
    return [{'repository': repository_name, 'revision': line} for line in output.split('\n') if not regex.match(line)]


def fetch_available_builds(repository_name, url, train_version_map):
    output = urllib2.urlopen(url).read()
    try:
        xml = parseXmlString(output)
    except Exception, error:
        raise Exception(error, output)
    available_builds = []
    for image in xml.getElementsByTagName('baseASR'):
        id = text_content(image.getElementsByTagName('id')[0])
        train = text_content(image.getElementsByTagName('train')[0])
        build = text_content(image.getElementsByTagName('build')[0])
        if train not in train_version_map:
            continue
        available_builds.append({
            'repository': repository_name,
            'revision': train_version_map[train] + ' ' + build})

    return available_builds


if __name__ == "__main__":
    main(sys.argv)
