#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2015 Hamilton Kibbe <ham@hamiltonkib.be>
# Copyright 2022 Jan Götte <code@jaseg.de>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import pytest

from ..ipc356 import *
from ..cam import FileSettings

from .utils import *
from ..utils import Inch, MM


REFERENCE_FILES = [
        # TODO add more test files from github
        'allegro-2/MinnowMax_RevA1_IPC356A.ipc',
        'allegro/08_057494d-ipc356.ipc',
        'ipc-d-356.ipc',
        ]


@filter_syntax_warnings
@pytest.mark.parametrize('reference', REFERENCE_FILES, indirect=True)
def test_read(reference):
    netlist = Netlist.open(reference)
    assert netlist
    assert netlist.test_records

@filter_syntax_warnings
@pytest.mark.parametrize('reference', REFERENCE_FILES, indirect=True)
def test_idempotence(reference, tmpfile):
    tmp_1 = tmpfile('First generation output', '.ipc')
    tmp_2 = tmpfile('Second generation output', '.ipc')

    a = Netlist.open(reference)
    a.save(tmp_1)
    b = Netlist.open(tmp_1)
    b.save(tmp_2)

    print(f'{a.outlines=}')
    print(f'{b.outlines=}')

    res = tmp_1.read_text() == tmp_2.read_text()
    # Confuse pytest so it doesn't try to print out a diff. pytest's potato diff algorithm is wayyyy to slow and would
    # hang for several minutes.
    assert res

@filter_syntax_warnings
@pytest.mark.parametrize('reference', REFERENCE_FILES, indirect=True)
def test_bells_and_whistles(reference):
    netlist = Netlist.open(reference)
    netlist.net_names()
    netlist.vias()
    netlist.reference_designators()
    netlist.records_by_reference('C1')
    netlist.records_by_net_name('n001')
    netlist.conductors_by_net_name('n001')
    netlist.conductors_by_layer(0)

@filter_syntax_warnings
@pytest.mark.parametrize('a', REFERENCE_FILES)
@pytest.mark.parametrize('b', REFERENCE_FILES)
def test_merge(a, b):
    a, b = reference_path(a), reference_path(b)
    print('File A:', a)
    print('File B:', a)

    a = Netlist.open(a)
    b = Netlist.open(b)
    a.merge(b, our_prefix='A')
    # FIXME asserts

def test_record_semantics():
    settings = FileSettings()
    r = TestRecord.parse('327m0002            CPU1  -AY30       A01X+020114Y+014930X0120Y    R090 S1      ', settings)
    assert r.pad_type == PadType.SMD_PAD
    assert r.net_name == 'm0002'
    assert r.is_connected
    assert r.ref_des == 'CPU1'
    assert not r.is_via
    assert r.pin == 'AY30'
    assert not r.is_middle
    assert r.hole_dia is None
    assert r.is_plated is None
    assert r.access_layer == 1
    assert math.isclose(r.x, 20114/1000) and math.isclose(r.y, 14930/1000)
    assert math.isclose(r.w, 120/1000) and r.h is None
    assert math.isclose(r.rotation, math.pi/2)
    assert r.solder_mask == SoldermaskInfo.PRIMARY
    assert r.unit == settings.unit

    r = TestRecord.parse('327m0002            U15   -D3         A01X+011545Y+003447X0090Y    R090 S1      ', settings)
    assert r.pad_type == PadType.SMD_PAD
    assert r.net_name == 'm0002'
    assert r.is_connected
    assert r.ref_des == 'U15'
    assert r.pin == 'D3'
    assert not r.is_middle
    assert r.hole_dia is None
    assert r.is_plated is None
    assert r.access_layer == 1
    assert math.isclose(r.w, 90/1000) and r.h is None

    r = TestRecord.parse('327VSUMPG           C39   -2   M      A01X+013050Y+020050X0350Y0320R270 S1      ', settings)
    assert r.pad_type == PadType.SMD_PAD
    assert r.net_name == 'VSUMPG'
    assert r.is_connected
    assert r.ref_des == 'C39'
    assert r.pin == '2'
    assert r.is_middle
    assert r.hole_dia is None
    assert r.is_plated is None
    assert r.access_layer == 1
    assert math.isclose(r.w, 350/1000) and math.isclose(r.h, 320/1000)
    assert math.isclose(r.rotation, math.pi*3/2)

    r = TestRecord.parse('327N/C              CPU1  -AD2        A01X+023191Y+020393X0110Y    R090 S1      ', settings)
    assert r.pad_type == PadType.SMD_PAD
    assert r.net_name == None
    assert not r.is_connected
    assert r.ref_des == 'CPU1'
    assert r.pin == 'AD2'
    assert r.hole_dia is None
    assert r.is_plated is None
    assert r.access_layer == 1
    assert math.isclose(r.w, 110/1000) and r.h is None

    r = TestRecord.parse('317m0002            VIA   -    MD0080PA00X+011900Y+004000X0160Y         S3      ', settings)
    assert r.pad_type == PadType.THROUGH_HOLE
    assert r.net_name == 'm0002'
    assert r.is_connected
    assert r.ref_des is None
    assert r.is_via
    assert r.pin is None
    assert r.is_middle
    assert r.hole_dia == 80/1000
    assert r.is_plated
    assert r.access_layer == 0
    assert math.isclose(r.w, 160/1000) and r.h is None
    assert r.rotation == 0
    assert r.solder_mask == SoldermaskInfo.BOTH

    r = TestRecord.parse('317GND              VIA   -    MD0080PA00X+023800Y+010100X0160Y         S0      ', settings)
    assert r.pad_type == PadType.THROUGH_HOLE
    assert r.net_name == 'GND'
    assert r.is_connected
    assert r.is_via
    assert r.pin is None
    assert r.hole_dia == 80/1000
    assert r.is_plated
    assert r.access_layer == 0
    assert r.solder_mask == SoldermaskInfo.NONE

def test_record_idempotence():
    records = [
            '327m0002            CPU1  -AY30       A01X+020114Y+014930X0120Y    R090 S1      ',
            '327m0002            U15   -D3         A01X+011545Y+003447X0090Y    R090 S1      ',
            '327VSUMPG           C39   -2   M      A01X+013050Y+020050X0350Y0320R270 S1      ',
            '317m0002            VIA   -    MD0080PA00X+011900Y+004000X0160Y         S3      ',
            '317GND              VIA   -    MD0080PA00X+023800Y+010100X0160Y         S0      ',]

    for unit in MM, Inch:
        settings = FileSettings(unit=unit)
        for record in records:
            ra = TestRecord.parse(record, settings)
            a = list(ra.format(settings))[0]
            rb = TestRecord.parse(a, settings)
            b = list(rb.format(settings))[0]
            print('ra', ra)
            print('rb', rb)
            print('0', record)
            print('a', a)
            print('b', b)
            assert a == b