#!python
###############################################################################
# (c) Copyright 2013 CERN                                                     #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
'''
Query the results database to find missing tests and produce the
expected_builds.json file needed to re-schedule them.
'''
from LbNightlyTools import Dashboard
from LbNightlyTools.Scripts.Common import addDashboardOptions

from datetime import date
import time
import json

# Parse command line
from optparse import OptionParser
parser = OptionParser(description=__doc__)

parser.add_option(
    '--day',
    action='store',
    help='day to check as yyyy-mm-dd (default: today)',
    default=str(date.today()))
parser.add_option(
    '-o',
    '--output',
    action='store',
    help='output file name [default: standard output]')
addDashboardOptions(parser)

opts, args = parser.parse_args()

if args:
    parser.error('unexpected arguments')

# Initialize db connection
dashboard = Dashboard(
    credentials=None,
    flavour=opts.flavour,
    server=opts.db_url,
    dbname=opts.db_name or Dashboard.dbName(opts.flavour))

# Prepare data
day_start = time.mktime(time.strptime(opts.day, '%Y-%m-%d'))
expected_builds = []


def expected_build_info(slot, project, platform, timestamp):
    from os.path import join
    version = None
    for p in slot['projects']:
        if project == p['name'] and not p.get('no_test'):
            version = p['version']
            break
    else:
        # cannot find the project in the slot or the project is not tested
        return None
    build_id = str(slot['build_id'])
    filename = join(
        'artifacts', opts.flavour, slot['slot'], build_id,
        '.'.join([project, version, slot['slot'], build_id, platform, 'zip']))
    return [
        filename, slot['slot'], slot['build_id'], project, platform, timestamp,
        platform.split('-')[1]
    ]


for row in dashboard.db.iterview(
        'summaries/byDay', batch=100, key=opts.day, include_docs=True):
    slot_name = row.doc['slot']
    build_id = row.doc['build_id']

    for platform in row.doc['config']['platforms']:
        builds = set()
        tests = set()
        started = day_start
        if platform in row.doc['builds']:
            builds.update(p for p in row.doc['builds'][platform] if p != 'info'
                          and 'completed' in row.doc['builds'][platform][p])
            started = row.doc['builds'][platform]['info']['started']
        if platform in row.doc['tests']:
            tests.update(p for p in row.doc['tests'][platform]
                         if 'completed' in row.doc['builds'][platform][p])
        expected_builds.extend(
            expected_build_info(row.doc['config'], project, platform, started)
            for project in builds - tests)

if opts.output:
    import codecs
    json.dump(
        expected_builds, codecs.open(opts.output, 'w', 'utf-8'), indent=2)
else:
    print json.dumps(expected_builds, indent=2)
