#!/usr/bin/python3

# Copyright © 2011, 2012, 2013 Jakub Wilk
#
# This program is free software.  It is distributed 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.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, you can find it on the World Wide Web at
# http://www.gnu.org/copyleft/gpl.html, or write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import glob
import os
import re

import deb822

import misc

_lintian_line_re = re.compile(r'^(?P<type>[a-z]): (?P<package>[a-z0-9][a-z0-9.+-]+)(?: (?P<pkgtype>[a-z]+))?: (?P<tag>[a-zA-Z0-9._-]+)( (?P<extra>.+))?$')

def tag_from_lintian_line(line):
    match = _lintian_line_re.match(line)
    if match is None:
        raise ValueError('cannot parse lintian line: {line!r}'.format(line=line))
    return match.group('tag')

def count_tags(lintian_output, d):
    lines = filter(None, [s.lstrip() for s in lintian_output.splitlines()])
    done = set()
    for line in lines:
        tag = tag_from_lintian_line(line)
        if tag in done:
            continue
        d[tag] += 1
        done.add(tag)

def main():
    os.chdir(misc.root)
    update_blackbox_coverage()
    update_code_analysis_coverage()

def read_tags(path):
    tags = {}
    with open(path, 'rt', encoding='UTF-8') as file:
        for para in deb822.Deb822.iter_paragraphs(file):
            try:
                tags[para['tag']] = 0
            except LookupError:
                continue
    return tags

def print_coverage(tags, file):
    for tag, n in sorted(tags.items()):
        c = {0: ' ', 1: 'X'}.get(n, n)
        print('| [{c}] {tag}'.format(c=c, tag=tag), file=file)

def update_blackbox_coverage(stdout=None):
    if stdout is None:
        with open('tests/blackbox/coverage.txt', 'wt', encoding='UTF-8') as stdout:
            return update_blackbox_coverage(stdout=stdout)
    for filename in sorted(glob.glob('checks/python/*.desc')):
        check, _ = os.path.splitext(os.path.basename(filename))
        tags_for = read_tags(filename)
        tags_against = tags_for.copy()
        tdesc_filename = 'tests/blackbox/{check}.t'.format(check=check)
        if os.path.exists(tdesc_filename):
            with open(tdesc_filename, 'rt', encoding='UTF-8') as file:
                for para in deb822.Deb822.iter_paragraphs(file):
                    count_tags(para.get('test-for', ''), tags_for)
                    count_tags(para.get('test-against', ''), tags_against)
        print(check, file=stdout)
        print('~' * len(check), file=stdout)
        print_coverage(tags_for, file=stdout)
        print(file=stdout)

def update_code_analysis_coverage():
    path = 'checks/python/code-analysis.desc'
    tags = read_tags(path)
    for path in glob.glob('tests/code-analysis/*.t-ca'):
        done = set()
        with open(path, 'rt', encoding='UTF-8') as file:
            for line in file:
                if line.startswith('# '):
                    _, tag, *_ = line.split()
                    done.add(tag)
                else:
                    break
        for tag in done:
            tags[tag] += 1
    with open('tests/code-analysis/coverage.txt', 'wt', encoding='UTF-8') as stdout:
        print_coverage(tags, file=stdout)

if __name__ == '__main__':
    main()

# Local Variables:
# indent-tabs-mode: nil
# End:
# vim: syntax=python sw=4 sts=4 sr et
