"""
Tests of Gerber format.
- Simple 2 layers
- Inner layer

For debug information use:
pytest-3 --log-cli-level debug
"""

import os
import sys
# Look for the 'utils' module from where the script is running
prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if prev_dir not in sys.path:
    sys.path.insert(0, prev_dir)
# Utils import
from utils import context
from kibot.misc import (PLOT_ERROR)


GERBER_DIR = 'gerberdir'
ALL_LAYERS = ['B_Adhes',
              'B_CrtYd',
              'B_Cu',
              'B_Fab',
              'B_Mask',
              'B_Paste',
              'B_SilkS',
              'Cmts_User',
              'Dwgs_User',
              'Eco1_User',
              'Eco2_User',
              'Edge_Cuts',
              'F_Adhes',
              'F_CrtYd',
              'F_Cu',
              'F_Fab',
              'F_Mask',
              'F_Paste',
              'F_SilkS',
              'Margin',
              ]
ALL_EXTS = ['gba',
            'gbr',
            'gbl',
            'gbr',
            'gbs',
            'gbp',
            'gbo',
            'gbr',
            'gbr',
            'gbr',
            'gbr',
            'gm1',
            'gta',
            'gbr',
            'gtl',
            'gbr',
            'gts',
            'gtp',
            'gto',
            'gbr',
            ]
INNER_LAYERS = ['GND_Cu',
                'Power_Cu',
                'Signal1_Cu',
                'Signal2_Cu',
                ]
INNER_EXTS = ['g2',
              'g5',
              'g3',
              'g4',
              ]


def test_gerber_2layer(test_dir):
    prj = 'simple_2layer'
    ctx = context.TestContext(test_dir, 'Simple_2_layer', prj, prj, GERBER_DIR)
    ctx.run()

    f_cu = ctx.get_gerber_filename('F_Cu')
    ctx.expect_out_file(f_cu)
    ctx.expect_out_file(ctx.get_gerber_job_filename())

    ctx.expect_gerber_has_apertures(f_cu, [
        r"C,0.200000",
        r"R,2.000000X2.000000",
        r"C,1.000000"])

    # expect a flash for the square pad
    ctx.expect_gerber_flash_at(f_cu, 5, (140, -100))

    ctx.clean_up()


def test_gerber_inner_ok(test_dir):
    prj = 'good-project'
    ctx = context.TestContext(test_dir, 'Gerber_Inner', prj, 'gerber_inner', GERBER_DIR)
    rarfile = prj+'-result.rar'
    ctx.create_dummy_out_file(rarfile)
    ctx.run()
    files = [prj+'_GND_Cu.gbr', prj+'_Signal1.gbr', 'test-'+prj+'.gbrjob']
    files = [os.path.join(GERBER_DIR, f) for f in files]
    for f in files:
        ctx.expect_out_file(f)
    ctx.test_compress(rarfile, files)
    ctx.clean_up()


def test_gerber_inner_wrong(test_dir):
    prj = 'good-project'
    ctx = context.TestContext(test_dir, 'Gerber_InnerWrong', prj, 'gerber_inner_wrong', GERBER_DIR)
    ctx.run(PLOT_ERROR)
    assert ctx.search_err('is not valid for this board')
    ctx.clean_up()


def compose_fname(dir, prefix, layer, suffix, ext='gbr'):
    return os.path.join(dir, prefix+'-'+layer+suffix+'.'+ext)


def check_layers_exist(ctx, dir, prefix, layers, suffix):
    for layer in layers:
        ctx.expect_out_file(compose_fname(dir, prefix, layer, suffix))
    ctx.expect_out_file(compose_fname(dir, prefix, 'job', suffix, 'gbrjob'))


def check_components(ctx, dir, prefix, layers, suffix, exclude, include):
    for layer in layers:
        fname = compose_fname(dir, prefix, layer, suffix)
        inc = [r'%TO\.C,{}\*%'.format(v) for v in include]
        ctx.search_in_file(fname, inc)
        exc = [r'%TO\.C,{}\*%'.format(v) for v in exclude]
        ctx.search_not_in_file(fname, exc)


def test_gerber_variant_1(test_dir):
    prj = 'kibom-variant_3'
    ctx = context.TestContext(test_dir, 'test_gerber_variant_1', prj, 'gerber_variant_1', GERBER_DIR)
    ctx.run()
    # R3 is a component added to the PCB, included in all cases
    # variant: default     directory: gerber      components: R1, R2 and R3
    check_layers_exist(ctx, 'gerber', prj, ALL_LAYERS, '')
    check_components(ctx, 'gerber', prj, ['F_Paste', 'F_Adhes'], '', ['C1', 'C2'], ['R1', 'R2', 'R3'])
    # variant: production  directory: production  components: R1, R2, R3 and C2
    check_layers_exist(ctx, 'production', prj, ALL_LAYERS, '_(production)')
    check_components(ctx, 'production', prj, ['F_Paste', 'F_Adhes'], '_(production)', ['C1'], ['R1', 'R2', 'R3', 'C2'])
    # variant: test        directory: test        components: R1, R3 and C2
    check_layers_exist(ctx, 'test', prj, ALL_LAYERS, '_(test)')
    check_components(ctx, 'test', prj, ['F_Paste', 'F_Adhes'], '_(test)', ['R2'], ['C1', 'R1', 'R3', 'C2'])
    ctx.clean_up(keep_project=True)


def test_gerber_protel_1(test_dir):
    prj = 'good-project'
    ctx = context.TestContext(test_dir, 'test_gerber_protel_1', prj, 'gerber_inner_protel_1', GERBER_DIR)
    ctx.run()
    exts = ALL_EXTS+INNER_EXTS
    for n, suf in enumerate(ALL_LAYERS+INNER_LAYERS):
        ctx.expect_out_file(os.path.join(GERBER_DIR, prj+'_'+suf+'.'+exts[n]))
    ctx.clean_up()


def test_gerber_protel_2(test_dir):
    prj = 'good-project'
    ctx = context.TestContext(test_dir, 'test_gerber_protel_2', prj, 'gerber_inner_protel_2', GERBER_DIR)
    ctx.run(extra_debug=True)
    inner = ['gin'+str(int(layer[-1])-1) for layer in INNER_EXTS]
    exts = ALL_EXTS+inner
    files = []
    for n, suf in enumerate(ALL_LAYERS+INNER_LAYERS):
        ext = exts[n]
        if ext == 'gm1':
            ext = 'e_cut'
        file = os.path.join(GERBER_DIR, prj+'_'+suf+'.'+ext.upper())
        ctx.expect_out_file(file)
        files.append(file)
    assert ctx.search_err('Layer "Inner layer 6" isn\'t used')
    ctx.search_in_file(os.path.join(GERBER_DIR, 'Report.txt'),
                       ['Top layer: good-project_F_Cu.GTL', 'Basename: good-project'])
    ctx.test_compress(prj+'-result.tar.gz', files)
    ctx.clean_up()
