#!/usr/bin/env python
# coding: utf-8

from waflib import Task, Options, Utils, Logs
import re

class check_output(Task.Task):

    def runnable_status(self):
        if self.generator.bld.variant == 'debug':
            print("WARNING: skipping output verification for the `debug' variant")
            return Task.SKIP_ME
        if getattr(Options.options, 'no_tests', False):
            return Task.SKIP_ME
        ret = super(check_output, self).runnable_status()
        if ret == Task.SKIP_ME:
            if getattr(Options.options, 'all_tests', False):
                return Task.RUN_ME
        return ret

    def run(self):
        # pattern for a generating vector
        genpat = re.compile(r'(lattice\([^,]+,\s*)(\[[^\]]+)\](\s*\))')
        genrepl = r'\1[<GEN>]\3'
        # check that the output is consistent
        outpath = self.generator.bld.path.find_dir('examples/tutorial/output')
        for i, (target, status, out, err) in enumerate(self.generator.bld.utest_results):
            name = self.generator.bld.root.find_node(target).name
            outcheck = Utils.readf(outpath.find_node(name + '.txt').abspath())
            if type(out) == bytes:
                out = out.decode()
            # skip the generating vectors
            out = genpat.sub(genrepl, out)
            outcheck = genpat.sub(genrepl, outcheck)
            # compare
            if out.strip() != outcheck.strip():
                status = -1
                Logs.warn('=====================================================================')
                Logs.warn('Test `{}\' failed:'.format(name))
                linescheck = [re.sub(r'\s\+$', '', s) for s in outcheck.split('\n')]
                lines      = [re.sub(r'\s\+$', '', s) for s in out     .split('\n')]
                # pad outputs
                linescheck += [''] * max(0, len(lines) - len(linescheck))
                lines      += [''] * max(0, len(linescheck) - len(lines))
                # line by line comparison
                for line, linecheck in zip(lines, linescheck):
                    if line != linecheck:
                        Logs.error('EXPECTED| {}'.format(linecheck))
                        Logs.error('  ACTUAL| {}'.format(line))
                    else:
                        Logs.warn('        | {}'.format(line))
                Logs.warn('=====================================================================')
            self.generator.bld.utest_results[i] = target, status, out, err

def build(ctx):

    lc_inc_dir = ctx.root.find_dir(ctx.top_dir).find_dir('latcommon/include')
    lb_inc_dir = ctx.root.find_dir(ctx.top_dir).find_dir('latbuilder/include')

    targets = []
    for src in ctx.path.ant_glob('*.cc'):

        targets.append(ctx.path.find_or_declare(src.name[:-3]))

        ctx(features='cxx cxxprogram test',
                source=src,
                includes=[lb_inc_dir, lc_inc_dir],
                lib=ctx.env.LIB_FFTW + ctx.env.LIB_PROGRAM_OPTIONS + ctx.env.LIB_RT,
                stlib=ctx.env.STLIB_FFTW + ctx.env.STLIB_PROGRAM_OPTIONS,
                target=targets[-1],
                use=['latbuilder', 'latcommon'],
                install_path=None)

    ctx.install_files('${DOCDIR}/examples/tutorial', ctx.path.ant_glob('*.cc'))

    from waflib.Tools import waf_unit_test
    ctx.add_post_fun(waf_unit_test.summary)

    ctx.add_group()

    check_output_task = check_output(env=ctx.env)
    check_output_task.set_inputs(targets)
    ctx.add_to_group(check_output_task)
