# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import datetime
import json
import logging
import sys
import traceback
import urllib2
import webapp2

from google.appengine.api import memcache

MASTERS = [
    {'name': 'ChromiumWin', 'url': 'http://build.chromium.org/p/chromium.win', 'groups': ['@ToT Chromium']},
    {'name': 'ChromiumMac', 'url': 'http://build.chromium.org/p/chromium.mac', 'groups': ['@ToT Chromium']},
    {'name': 'ChromiumLinux', 'url': 'http://build.chromium.org/p/chromium.linux', 'groups': ['@ToT Chromium']},
    {'name': 'ChromiumChromiumOS', 'url': 'http://build.chromium.org/p/chromium.chromiumos', 'groups': ['@ToT ChromeOS']},
    {'name': 'ChromiumGPU', 'url': 'http://build.chromium.org/p/chromium.gpu', 'groups': ['@ToT Chromium']},
    {'name': 'ChromiumGPUFYI', 'url': 'http://build.chromium.org/p/chromium.gpu.fyi', 'groups': ['@ToT Chromium FYI']},
    {'name': 'ChromiumPerfAv', 'url': 'http://build.chromium.org/p/chromium.perf_av', 'groups': ['@ToT Chromium']},
    {'name': 'ChromiumWebkit', 'url': 'http://build.chromium.org/p/chromium.webkit', 'groups': ['@ToT Chromium', '@ToT Blink']},
    {'name': 'ChromiumFYI', 'url': 'http://build.chromium.org/p/chromium.fyi', 'groups': ['@ToT Chromium FYI']},
    {'name': 'V8', 'url': 'http://build.chromium.org/p/client.v8', 'groups': ['@ToT V8']},
]


class FetchBuildersException(Exception): pass


def master_json_url(master_url):
    return master_url + '/json/builders'


def builder_json_url(master_url, builder):
    return master_json_url(master_url) + '/' + urllib2.quote(builder)


def cached_build_json_url(master_url, builder, build_number):
    return builder_json_url(master_url, builder) + '/builds/' + str(build_number)


def fetch_json(url):
    logging.debug('Fetching %s' % url)
    fetched_json = {}
    try:
        resp = urllib2.urlopen(url)
    except:
        exc_info = sys.exc_info()
        logging.warning('Error while fetching %s: %s', url, exc_info[1])
        return fetched_json

    try:
        fetched_json = json.load(resp)
    except:
        exc_info = sys.exc_info()
        logging.warning('Unable to parse JSON response from %s: %s', url, exc_info[1])

    return fetched_json


def get_latest_build(build_data):
    cached_builds = []
    if 'cachedBuilds' in build_data:
        cached_builds = build_data['cachedBuilds']

    current_builds = build_data['currentBuilds']

    latest_cached_builds = set(cached_builds) - set(current_builds)
    if len(latest_cached_builds) != 0:
        latest_cached_builds = sorted(list(latest_cached_builds))
        latest_build = latest_cached_builds[-1]
    elif len(current_builds) != 0:
        latest_build = current_builds[0]
    else:
        basedir = build_data['basedir'] if 'basedir' in build_data else 'current builder'
        logging.info('No cached or current builds for %s', basedir)
        return None

    return latest_build


def dump_json(data):
    return json.dumps(data, separators=(',', ':'), sort_keys=True)


def fetch_buildbot_data(masters, force_update=False):
    if force_update:
        logging.info('Starting a forced buildbot update. Failure to fetch a master\'s data will not abort the fetch.')

    start_time = datetime.datetime.now()
    master_data = masters[:]
    for master in master_data:
        master_url = master['url']
        tests_object = master.setdefault('tests', {})
        master['tests'] = tests_object

        builders = fetch_json(master_json_url(master_url))
        if not builders:
            msg = 'Could not fetch builders from master "%s": %s.' % (master['name'], master_url)
            logging.warning(msg)
            if force_update:
                continue
            else:
                logging.warning('Aborting fetch.')
                raise FetchBuildersException(msg)

        for builder in builders:
            build_data = fetch_json(builder_json_url(master_url, builder))

            latest_build = get_latest_build(build_data)
            if not latest_build:
                logging.info('Skipping builder %s because it lacked cached or current builds.', builder)
                continue

            build = fetch_json(cached_build_json_url(master_url, builder, latest_build))
            if not build:
                logging.info('Skipping build %s on builder %s due to empty data', latest_build, builder)
            for step in build['steps']:
                step_name = step['name']
                is_test_step = 'test' in step_name and 'archive' not in step_name and 'Run tests' not in step_name
                if not is_test_step:
                    continue

                if step_name == 'webkit_tests':
                    step_name = 'layout-tests'

                tests_object.setdefault(step_name, {'builders': []})
                tests_object[step_name]['builders'].append(builder)

        for builders in tests_object.values():
            builders['builders'].sort()

    output_data = {'masters': master_data}

    delta = datetime.datetime.now() - start_time

    logging.info('Fetched buildbot data in %s seconds.', delta.seconds)

    return dump_json(output_data)


class UpdateBuilders(webapp2.RequestHandler):
    """Fetch and update the cached buildbot data."""
    def get(self):
        force_update = True if self.request.get('force') else False
        try:
            buildbot_data = fetch_buildbot_data(MASTERS, force_update)
            memcache.set('buildbot_data', buildbot_data)
            self.response.set_status(200)
            self.response.out.write("ok")
        except FetchBuildersException, ex:
            logging.error('Not updating builders because fetch failed: %s', str(ex))
            self.response.set_status(500)
            self.response.out.write(ex.message)



class GetBuilders(webapp2.RequestHandler):
    """Return a list of masters mapped to their respective builders, possibly using cached data."""
    def get(self):
        callback = self.request.get('callback')

        buildbot_data = memcache.get('buildbot_data')

        if not buildbot_data:
            logging.warning('No buildbot data in memcache. If this message repeats, something is probably wrong with memcache.')

            # Since we have no cached buildbot data, we would rather have missing masters than no data at all.
            buildbot_data = fetch_buildbot_data(MASTERS, True)
            try:
                memcache.set('buildbot_data', buildbot_data)
            except ValueError, err:
                logging.error(str(err))

        if callback:
            buildbot_data = callback + '(' + buildbot_data + ');'

        self.response.out.write(buildbot_data)
