import pytest
from asn1PERser.codec.per.decoder import decode as per_decoder
from asn1PERser.test.per.encoder.test_per_encode_enumerated import SCHEMA_my_enum, \
    SCHEMA_my_ext_enum, short_enum, enumeration_list, DATA_my_enum


@pytest.mark.parametrize("schema, encoded, value", [
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2]), '00',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2]), 'e0')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2]), '80',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2]), 'e1')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:10]), '90',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:10]), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:17]), '48',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:17]), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33]), '24',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33]), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33]), '80',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33]), 'e32')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:100]), 'C4',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:100]), 'e98')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), '7E',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), 'e126')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), '7F',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), 'e127')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), '80',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130]), 'e128')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), '0080',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), 'e128')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), '00FE',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), 'e254')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), '00FF',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), 'e255')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), '0100',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260]), 'e256')),
])
def test_no_extension_marker_enumerated_can_be_decoded(schema, encoded, value):
    assert per_decoder(per_stream=bytearray.fromhex(encoded), asn1Spec=schema()) == value


@pytest.mark.parametrize("schema, encoded, value", [
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2], extensionMarker_value=True), '00',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2], extensionMarker_value=True), 'e0')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2], extensionMarker_value=True), '40',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:2], extensionMarker_value=True), 'e1')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:10], extensionMarker_value=True), '48',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:10], extensionMarker_value=True), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:17], extensionMarker_value=True), '24',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:17], extensionMarker_value=True), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33], extensionMarker_value=True), '12',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33], extensionMarker_value=True), 'e9')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33], extensionMarker_value=True), '40',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:33], extensionMarker_value=True), 'e32')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:100], extensionMarker_value=True), '62',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:100], extensionMarker_value=True), 'e98')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), '3F00',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), 'e126')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), '3F80',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), 'e127')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), '4000',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:130], extensionMarker_value=True), 'e128')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), '000080',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), 'e128')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), '0000FE',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), 'e254')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), '0000FF',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), 'e255')),
    (SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), '000100',
        DATA_my_enum(SCHEMA_my_enum(enumerationRoot_list=enumeration_list[0:260], extensionMarker_value=True), 'e256')),
])
def test_extension_marker_is_present_and_extension_addition_is_empty_but_value_is_from_root_can_be_decoded(schema, encoded, value):
    assert per_decoder(per_stream=bytearray.fromhex(encoded), asn1Spec=schema()) == value


@pytest.mark.parametrize("schema, encoded, value", [
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:2], extensionAddition_list=short_enum, extensionMarker_value=True), '00',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:2], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e0')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:2], extensionAddition_list=short_enum, extensionMarker_value=True), '40',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:2], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e1')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:10], extensionAddition_list=short_enum, extensionMarker_value=True), '48',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:10], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:17], extensionAddition_list=short_enum, extensionMarker_value=True), '24',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:17], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:33], extensionAddition_list=short_enum, extensionMarker_value=True), '12',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:33], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:33], extensionAddition_list=short_enum, extensionMarker_value=True), '40',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:33], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e32')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:100], extensionAddition_list=short_enum, extensionMarker_value=True), '62',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:100], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e98')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum, extensionMarker_value=True), '3F00',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e126')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum, extensionMarker_value=True), '3F80',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e127')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum, extensionMarker_value=True), '4000',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:130], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e128')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum, extensionMarker_value=True), '000080',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e128')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum, extensionMarker_value=True), '0000FE',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e254')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum, extensionMarker_value=True), '0000FF',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e255')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum, extensionMarker_value=True), '000100',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=enumeration_list[0:260], extensionAddition_list=short_enum,
                                        extensionMarker_value=True), 'e256')),
])
def test_extension_marker_is_present_and_extension_addition_is_not_empty_but_value_is_from_root_can_be_decoded(schema, encoded, value):
    assert per_decoder(per_stream=bytearray.fromhex(encoded), asn1Spec=schema()) == value


@pytest.mark.parametrize("schema, encoded, value", [
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:2], extensionMarker_value=True), '80',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:2],
                                        extensionMarker_value=True), 'e0')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:2], extensionMarker_value=True), '81',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:2],
                                        extensionMarker_value=True), 'e1')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:10], extensionMarker_value=True), '89',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:10],
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:17], extensionMarker_value=True), '89',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:17],
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:33], extensionMarker_value=True), '89',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:33],
                                        extensionMarker_value=True), 'e9')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:33], extensionMarker_value=True), 'A0',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:33],
                                        extensionMarker_value=True), 'e32')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:100], extensionMarker_value=True), 'C00162',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:100],
                                        extensionMarker_value=True), 'e98')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130], extensionMarker_value=True), 'C0017E',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130],
                                        extensionMarker_value=True), 'e126')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130], extensionMarker_value=True), 'C0017F',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130],
                                        extensionMarker_value=True), 'e127')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130], extensionMarker_value=True), 'C00180',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:130],
                                        extensionMarker_value=True), 'e128')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260], extensionMarker_value=True), 'C00180',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260],
                                        extensionMarker_value=True), 'e128')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260], extensionMarker_value=True), 'C001FE',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260],
                                        extensionMarker_value=True), 'e254')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260], extensionMarker_value=True), 'C001FF',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260],
                                        extensionMarker_value=True), 'e255')),
    (SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260], extensionMarker_value=True), 'C0020100',
        DATA_my_enum(SCHEMA_my_ext_enum(enumerationRoot_list=short_enum, extensionAddition_list=enumeration_list[0:260],
                                        extensionMarker_value=True), 'e256')),
])
def test_extension_marker_is_present_and_value_is_from_extension_can_be_decoded(schema, encoded, value):
    assert per_decoder(per_stream=bytearray.fromhex(encoded), asn1Spec=schema()) == value
