#!/usr/bin/env 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)
