#!/usr/bin/env python

# Copyright (c) 2009 Anthony Towns
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

import codecs, io, sys, yaml

from collections import OrderedDict

########################################################### formatting helpers

def FAIL(value): return ("#e87272",value)
def WARN(value): return ("#ccff66",value)
def PASS(value): return ("#60e760",value)

def c_truth(value):
    if value in [ True, "yes", "(yes)"]:
        return PASS("yes")
    elif value == False or value == "no":
        return FAIL("no")
    elif value.startswith("yes: "):
        return PASS(value)
    elif value.startswith("no: "):
        return FAIL(value)
    else:
        return WARN(value)

def c_untruth(value):
    if value == True or value == "yes":
        return FAIL("yes")
    elif value == False or value == "no":
        return PASS("no")
    elif value.startswith("yes: "):
        return FAIL(value)
    elif value.startswith("no: "):
        return PASS(value)
    else:
        return WARN(value)

def c_host(value):
    if not value:
        return FAIL("none")
    elif value.startswith("warn: "):
        value = value[6:]
        host, warning = value.split('; ')
        return WARN('<a href="http://db.debian.org/machines.cgi?host=%s">yes; %s</a>'%(host, warning))
    else:
        return PASS('<a href="http://db.debian.org/machines.cgi?host=%s">yes</a>'%(value))

def c_list(maybe,okay):
    def c_list_f(value):
        n=len(value)
        str='<abbr title="%s">%s</abbr>' % (", ".join(value),n)
        if n < maybe: return FAIL(str)
        if n >= okay: return PASS(str)
        return WARN(str)
    return c_list_f

def c_minmax_list(min,max):
    def c_minmax_list_f(value):
        n=len(value)
        str='<abbr title="%s">%s</abbr>' % (", ".join(value),n)
        if n < min or n > max: return FAIL(str)
        return PASS(str)
    return c_minmax_list_f

def c_num(maybe,okay):
    def c_list_f(value):
        if value < maybe: return FAIL(value)
        if value >= okay: return PASS(value)
        return WARN(value)
    return c_list_f

def c_str(value):
    if not value: return FAIL("-")
    return PASS(value)

def c_installer(value):
    if not value: return FAIL("-")
    if value == "d-i":
        return PASS(value)
    return WARN(value)

##################################################################### criteria

criteria = OrderedDict([
    ("available",         c_truth),
    ("portbox",           c_host),
    ("porters",           c_list(2,3)),
    ("installer",         c_installer),
    ("archive-coverage",  c_num(90,95)),
    ("archive-uptodate",  c_num(98,99)),
    ("upstream-support",  c_truth),
    ("buildds",           c_minmax_list(2,10)),
    ("buildd-dsa",        c_truth),
    ("autopkgtest",       c_truth),
    ("concerns-rm",       c_untruth),
    ("concerns-srm",      c_untruth),
    ("concerns-dsa",      c_untruth),
    ("concerns-sec",      c_untruth),
    ("candidate",         c_truth),
])

################################################################# table output

def dump_table(info,waivers):
    arches=list(info.keys())
    arches.sort()

    candidacy_at_risk = {}
    
    print("<table class='arch_qualify'>")
    print("<tr><th></th>")
    for arch in arches:
        print("<th class='arch'>%s</th>" % (arch))
        candidacy_at_risk[arch] = False
    print("</tr>")

    for c,c_fn in list(criteria.items()):
        print("<tr><th class='criteria'>%s</th>" % (c))
        for arch in arches:
            v=info[arch].get(c,None)

            if v is None and c=="candidate":
                if candidacy_at_risk[arch]:
                    v = "?"
                else:
                    v = "(yes)"

            col = None

            if v is None and c == "concerns-srm":
                crm_value = info[arch].get("concerns-rm", None)
                if crm_value is not None:
                    col,_ = criteria["concerns-rm"](crm_value)
                    contents = v = "as RM concerns"

            if col is None:
                if v is not None:
                    col,contents = c_fn(v)
                else:
                    col,contents = FAIL("-")

            w = waivers.get(arch,{}).get(c,None)
            if w:
                col="#00cccc"
                contents += ' <a href="%s">(w)</a>' % (w)

            if col==FAIL(None)[0]:
                candidacy_at_risk[arch]=True

            print('<td style="background-color:%s">%s</td>' % (col,contents))

        print("</tr>")

    print("</table>")

######################################################################### main

def main(argv):
    sys.stdout.reconfigure(encoding='utf-8')
    if len(argv) < 2 or argv[1] == "-h":
        print("Usage: %s <arch-spec.yaml> [<waivers-spec.yaml>]" % argv[0])
        sys.exit(1)

    info = yaml.safe_load(io.open(argv[1], encoding='utf-8'))
    if len(argv) >= 3:
        waivers=yaml.safe_load(io.open(argv[2], encoding='utf-8'))
    else:
        waivers={}

    dump_table(info,waivers)

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

