import re
from UniTAP.dev.modules.dut_tests.test_utils import TestReportConfigType, make_cf, CMTFormat, CMTBitDepth


def value_from_enumeration_var(_data, _value):

    if len(_data.str_presentation) > 0:
        return _data.str_presentation[_data.available_values.index(str(_value))]
    else:
        return _value


def copy_data(data):
    _data = {}
    for item in data:
        if item.config_id_name in ["TSI_DP14_SRCCTS_DUT_CAPS", "TSI_DP14_SRCCTS_DUT_TA",
                                   "TSI_DP14_SRCCTS_DMT_TIMING", "TSI_DP14_SRCCTS_CTA_TIMING",
                                   "TSI_DP14_SRCCTS_CVT_TIMING", "TSI_DP14_SRCCTS_AS_DUT_CAPS",
                                   "TSI_DP20_SRCCTS_DUT_CAPS", "TSI_DP20_SRCCTS_DUT_TA",
                                   "TSI_DP20_SRCCTS_DMT_TIMING", "TSI_DP20_SRCCTS_CTA_TIMING",
                                   "TSI_DP20_SRCCTS_CVT_TIMING", "TSI_DP20_SRCCTS_AS_DUT_CAPS",
                                   "TSI_DP20_SRCCTS_DUT_LINK_RATES", "TSI_DP14_SRCCTS_DUT_DEBUG_CONF",
                                   "TSI_DP20_SRCCTS_DUT_DEBUG_CONF", "TSI_DP20_SINKCTS_DEBUG_CONF"]:
            _data.update({item.config_id_name: [item.default_value, item.bit_field_list]})
        elif item.enumeration_variants is not None:
            _data.update({item.config_id_name: [item.default_value, item.enumeration_variants]})
        else:
            _data.update({item.config_id_name: item.default_value})
    return _data


def detect_warning_message(type_of_test: TestReportConfigType, data):
    _data = copy_data(data)
    _dict = {TestReportConfigType.Dp1_4_Source: "TSI_DP14_SRCCTS_DUT_DEBUG_CONF",
             TestReportConfigType.Dp2_1_Source: "TSI_DP20_SRCCTS_DUT_DEBUG_CONF",
             TestReportConfigType.Dp2_1_Sink: "TSI_DP20_SINKCTS_DEBUG_CONF",
             TestReportConfigType.Dp2_1_Lttpr: "TSI_DP20_LTTPR_DEBUG_CR_ITERATION_DELAY"}
    key = _dict.get(type_of_test)
    val = _data.get(key)
    if val is not None:
        if key in ["TSI_DP14_SRCCTS_DUT_DEBUG_CONF",
                   "TSI_DP20_SRCCTS_DUT_DEBUG_CONF",
                   "TSI_DP20_SINKCTS_DEBUG_CONF"] and val[0] != 0:
            return True
        elif key == "TSI_DP20_LTTPR_DEBUG_CR_ITERATION_DELAY" and int(val[0] != 100):
            return True
        else:
            return False
    else:
        return False


def update_configuration(type_of_test: TestReportConfigType, data):
    configuration = ""
    _data = copy_data(data)
    if type_of_test == TestReportConfigType.Dp1_4_Source:
        val = _data.get("TSI_DP14_SRCCTS_DUT_DEBUG_CONF")
        if val is not None and val[0] != 0:
            configuration += "<span class=DBG_HIGHLIGHT><br>Debug options:<br>"
            for _bit in val[1]:
                if val[0] & _bit.mask:
                    configuration += f" - {_bit.description}<br>"
            configuration += "<br>"

        configuration += "Test timeout = {}ms<br>".format(_data.get("TSI_DP14_SRCCTS_TIMEOUT"))
        configuration += "Long HPD Duration = {}ms<br><br>".format(_data.get("TSI_DP14_SRCCTS_LONG_HPD_PULSE"))
        configuration += "DUT capability settings and flags:<br>"
        configuration += "- Max lanes = {}<br>".format(_data.get("TSI_DP14_SRCCTS_MAX_LANES")[0])
        configuration += "- Max link rate = {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_MAX_LINK_RATE")[1],
                                       _data.get("TSI_DP14_SRCCTS_MAX_LINK_RATE")[0]))
        value = _data.get("TSI_DP14_SRCCTS_DUT_CAPS")
        dut_caps_value = int(value[0])
        for _bit in _data.get("TSI_DP14_SRCCTS_DUT_CAPS")[1]:
            if dut_caps_value & _bit.mask:
                configuration += "- {}<br>".format(_bit.description)

        configuration += "<br>Test automation flags and settings:<br>"

        ta_flags = ["Always ready", "EDID read", "Link Training end", "Active Video"]
        ta_flags_value = _data.get("TSI_DP14_SRCCTS_DUT_TA")[0]
        for bit in _data.get("TSI_DP14_SRCCTS_DUT_TA")[1]:
            if bit.mask & ta_flags_value or bit.enumeration_variants is not None:
                if bit.enumeration_variants is not None:
                    configuration += "- Event indicating DUT ready: {}<br>".format(
                        ta_flags[(ta_flags_value >> 3) & 0x3])
                else:
                    configuration += "- {}<br>".format(bit.description)

        fail_mode = "640 x 480 @ 60Hz 6 BPC"
        configuration += "<br>Failsafe timing: {}<br>".format(
            fail_mode if int(_data.get("TSI_DP14_SRCCTS_FAILSAFE_MODE")[0]) else "")
        configuration += "Max supported timing: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_MAX_RESOLUTION")[1],
                                       _data.get("TSI_DP14_SRCCTS_MAX_RESOLUTION")[0]))

        configuration += "<br>Most packed timings, 1 lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_1L_MOST_PACKED")[1],
                                       _data.get("TSI_DP14_SRCCTS_1L_MOST_PACKED")[0]))
        configuration += "Most packed timings, 2 lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_2L_MOST_PACKED")[1],
                                       _data.get("TSI_DP14_SRCCTS_2L_MOST_PACKED")[0]))
        configuration += "Most packed timings, 4 lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_4L_MOST_PACKED")[1],
                                       _data.get("TSI_DP14_SRCCTS_4L_MOST_PACKED")[0]))

        configuration += "<br>Time stamp generation timigns:<br>"
        configuration += "RBR, 1 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_1L_RBB")[1],
                                       _data.get("TSI_DP14_SRCCTS_1L_RBB")[0]))
        configuration += "RBR, 2 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_2L_RBB")[1],
                                       _data.get("TSI_DP14_SRCCTS_2L_RBB")[0]))
        configuration += "RBR, 4 Lane: {}<br><br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_4L_RBB")[1],
                                       _data.get("TSI_DP14_SRCCTS_4L_RBB")[0]))

        configuration += "HBR, 1 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_1L_HBR")[1],
                                       _data.get("TSI_DP14_SRCCTS_1L_HBR")[0]))
        configuration += "HBR, 2 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_2L_HBR")[1],
                                       _data.get("TSI_DP14_SRCCTS_2L_HBR")[0]))
        configuration += "HBR, 4 Lane: {}<br><br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_4L_HBR")[1],
                                       _data.get("TSI_DP14_SRCCTS_4L_HBR")[0]))

        configuration += "HBR2, 1 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_1L_HBR2")[1],
                                       _data.get("TSI_DP14_SRCCTS_1L_HBR2")[0]))
        configuration += "HBR2, 2 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_2L_HBR2")[1],
                                       _data.get("TSI_DP14_SRCCTS_2L_HBR2")[0]))
        configuration += "HBR2, 4 Lane: {}<br><br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_4L_HBR2")[1],
                                       _data.get("TSI_DP14_SRCCTS_4L_HBR2")[0]))

        configuration += "HBR3, 1 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_1L_HBR3")[1],
                                       _data.get("TSI_DP14_SRCCTS_1L_HBR3")[0]))
        configuration += "HBR3, 2 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_2L_HBR3")[1],
                                       _data.get("TSI_DP14_SRCCTS_2L_HBR3")[0]))
        configuration += "HBR3, 4 Lane: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_4L_HBR3")[1],
                                       _data.get("TSI_DP14_SRCCTS_4L_HBR3")[0]))

        configuration += "<br>Colorimetry:<br>"
        configuration += "- RGB 6 bpc VESA<br>"

        for i in range(1, 13):
            value = int(_data.get(f"TSI_DP14_SRCCTS_COLOR_MODE_{i}"))
            if value == make_cf(CMTFormat.RGB_LEGACY, CMTBitDepth.BPC_8):
                configuration += "- RGB 8 bpc VESA<br>"
            elif value == make_cf(CMTFormat.RGB_LEGACY, CMTBitDepth.BPC_10):
                configuration += "- RGB 10 bpc VESA<br>"
            elif value == make_cf(CMTFormat.RGB_CEA, CMTBitDepth.BPC_8):
                configuration += "- RGB 8 bpc CTA<br>"
            elif value == make_cf(CMTFormat.RGB_CEA, CMTBitDepth.BPC_10):
                configuration += "- RGB 10 bpc CTA<br>"
            elif value == make_cf(CMTFormat.YCBCR_422_BT601, CMTBitDepth.BPC_8):
                configuration += "- YCbCr 4:2:2 8 bpc CTA (ITU.601)<br>"
            elif value == make_cf(CMTFormat.YCBCR_422_BT601, CMTBitDepth.BPC_10):
                configuration += "- YCbCr 4:2:2 10 bpc CTA (ITU.601)<br>"
            elif value == make_cf(CMTFormat.YCBCR_422_BT709, CMTBitDepth.BPC_8):
                configuration += "- YCbCr 4:2:2 8 bpc CTA (ITU.709)<br>"
            elif value == make_cf(CMTFormat.YCBCR_422_BT709, CMTBitDepth.BPC_10):
                configuration += "- YCbCr 4:2:2 10 bpc CTA (ITU.709)<br>"
            elif value == make_cf(CMTFormat.YCBCR_444_BT601, CMTBitDepth.BPC_8):
                configuration += "- YCbCr 4:4:4 8 bpc CTA (ITU.601)<br>"
            elif value == make_cf(CMTFormat.YCBCR_444_BT601, CMTBitDepth.BPC_10):
                configuration += "- YCbCr 4:4:4 10 bpc CTA (ITU.601)<br>"
            elif value == make_cf(CMTFormat.YCBCR_444_BT709, CMTBitDepth.BPC_8):
                configuration += "- YCbCr 4:4:4 8 bpc CTA (ITU.709)<br>"
            elif value == make_cf(CMTFormat.YCBCR_444_BT709, CMTBitDepth.BPC_10):
                configuration += "- YCbCr 4:4:4 10 bpc CTA (ITU.709)<br>"

        configuration += "<br>Audio format:<br>"
        configuration += "- Minimum supported sample frequency: {}Hz<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_MIN_SAMPLE_RATE")[1],
                                       _data.get("TSI_DP14_SRCCTS_MIN_SAMPLE_RATE")[0]))
        configuration += "- Maximum supported sample frequency: {}Hz<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_MAX_SAMPLE_RATE")[1],
                                       _data.get("TSI_DP14_SRCCTS_MAX_SAMPLE_RATE")[0]))
        configuration += "- Audio test pattern: {}<br>". \
            format(value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_AUDIO_TEST_PATTERN")[1],
                                              _data.get("TSI_DP14_SRCCTS_AUDIO_TEST_PATTERN")[0]))
        configuration += "- Audio sample size: {}<br>". \
            format(value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_EDID_SAMPLE_SIZE")[1],
                                              _data.get("TSI_DP14_SRCCTS_EDID_SAMPLE_SIZE")[0]))

        ch_alloc_title = ["Minimum channel configuration / Min. sample rate",
                          "Maximum channel configuration / Min. sample rate",
                          "Minimum channel configuration / Max. sample rate",
                          "Maximum channel configuration / Max. sample rate"]

        ch_alloc_str = [
            "- Front Left + Front Right (2 Channels)",
            "- Low Frequency Effect (1 Channel)",
            "- Front Center (1 Channel)",
            "- Rear Left + Rear Right (2 Channels)",
            "- Rear Center (1 Channel)",
            "- Front Left Center + Front Right Center (2 Channels)",
            "- Rear Left Center + Rear Right Center (2 Channels)",
            "- Front Left Wide + Front Right Wide (2 Channels)",
            "- Front Left High + Front Right High (2 Channels)",
            "- Top Center (1 Channel)",
            "- Front Center High (1 Channel)"]

        for i in range(len(ch_alloc_title)):
            CH_ALLOC_CI = f"TSI_DP14_SRCCTS_CH_ALLOC{i + 1}"
            CH_ALLOC_VAL = int(_data.get(CH_ALLOC_CI))

            CH_COUNT_CI = f"TSI_DP14_SRCCTS_CHANNELS{i + 1}"
            CH_COUNT_VAL = int(_data.get(CH_COUNT_CI))

            configuration += "<br>{}:<br>".format(ch_alloc_title[i])
            configuration += "- Channel count: {}<br>".format(CH_COUNT_VAL)

            for j in range(len(ch_alloc_str)):
                if CH_ALLOC_VAL >> j & 1:
                    configuration += "{}<br>".format(ch_alloc_str[j])

        configuration += "<br>DSC Info:<br>"
        dsc_version = int(_data.get("TSI_DP14_SRCCTS_DSC_VERSION")[0])
        configuration += "- DSC Version: {}.{}<br>".format((dsc_version >> 16) & 0xff, dsc_version & 0xff)
        configuration += "- DSC Max. Slices: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_DSC_DUT_MAX_SLICE")[1],
                                       _data.get("TSI_DP14_SRCCTS_DSC_DUT_MAX_SLICE")[0]))

        configuration += "<br>DSC Colorimetry:<br>"
        configuration += "- RGB 8 bpc VESA<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_1")):
            configuration += "- RGB 10 bpc VESA<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_2")):
            configuration += "- RGB 12 bpc VESA<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_3")):
            configuration += "- YCbCr 4:4:4 8 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_4")):
            configuration += "- YCbCr 4:4:4 10 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_5")):
            configuration += "- YCbCr 4:4:4 12 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_6")):
            configuration += "- YCbCr 4:2:2 8 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_7")):
            configuration += "- YCbCr 4:2:2 10 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_8")):
            configuration += "- YCbCr 4:2:2 12 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_9")):
            configuration += "- YCbCr 4:2:2 Simple 8 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_10")):
            configuration += "- YCbCr 4:2:2 Simple 10 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_11")):
            configuration += "- YCbCr 4:2:2 Simple 12 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_12")):
            configuration += "- YCbCr 4:2:0 Simple 8 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_13")):
            configuration += "- YCbCr 4:2:0 Simple 10 bpc CTA (ITU.709)<br>"
        if int(_data.get("TSI_DP14_SRCCTS_DSC_COLOR_MODE_14")):
            configuration += "- YCbCr 4:2:0 Simple 12 bpc CTA (ITU.709)<br>"
        configuration += "<br>DSC resolutions to be tested:<br>"

        dsc_timings = ["1920x1080 @ 30Hz", "1920x1080 @ 60Hz", "1920x1080 @ 120Hz", "3840x2160 @ 30Hz",
                       "3840x2160 @ 60Hz", "3840x2160 @ 120Hz", "5120x2160 @ 30Hz", "5120x2160 @ 60Hz",
                       "5120x2160 @ 120Hz", "7680x4320 @ 30Hz", "7680x4320 @ 60Hz", "7680x4320 @ 100Hz"]

        for item in enumerate(dsc_timings):
            if int(_data.get(f"TSI_DP14_SRCCTS_DSC_VMT_{item[0]}_TIMINGS")):
                lane_count_link_rate = _data.get(f"TSI_DP14_SRCCTS_DSC_VMT_{item[0]}_LC_LR")
                if lane_count_link_rate in [1 << 0, 1 << 1, 1 << 2, 1 << 3]:
                    n_lanes = "1"
                elif lane_count_link_rate in [1 << 4, 1 << 5, 1 << 6, 1 << 7]:
                    n_lanes = "2"
                else:
                    n_lanes = "4"
                if lane_count_link_rate in [1 << 0, 1 << 4, 1 << 8]:
                    bit_rate = "1.62"
                elif lane_count_link_rate in [1 << 1, 1 << 5, 1 << 9]:
                    bit_rate = "2.7"
                elif lane_count_link_rate in [1 << 2, 1 << 6, 1 << 10]:
                    bit_rate = '5.4'
                else:
                    bit_rate = "8.1"
                configuration += "- {} with {} lanes(s) @ {} Gbps<br>".format(item[1], n_lanes, bit_rate)

        configuration += "<br>DisplayID test configuration:<br>"
        configuration += "- Max HActive = {}<br>".format(_data.get("TSI_DP14_SRCCTS_MAX_STREAM_HACTIVE"))
        configuration += "- Max VActive = {}<br>".format(_data.get("TSI_DP14_SRCCTS_MAX_STREAM_VACTIVE"))
        configuration += "- Max Pixel Clock (kHz) = {} <br>".format(
            _data.get("TSI_DP14_SRCCTS_MAX_STREAM_PIXEL_CLOCK"))

        if int(_data.get("TSI_DP14_SRCCTS_DUT_CAPS")[1][15].mask) & int(
                _data.get("TSI_DP14_SRCCTS_DUT_CAPS")[0]):
            configuration += "<br>DMT Timings:<br>"
            dmt_timing_value = int(_data.get("TSI_DP14_SRCCTS_DMT_TIMING")[0])
            for _bit in _data.get("TSI_DP14_SRCCTS_DMT_TIMING")[1]:
                if dmt_timing_value & int(_bit.mask):
                    configuration += "- {}<br>".format(_bit.description)

        if int(_data.get("TSI_DP14_SRCCTS_DUT_CAPS")[1][16].mask) & int(
                _data.get("TSI_DP14_SRCCTS_DUT_CAPS")[0]):
            configuration += "<br>CTA Timings:<br>"
            cta_timing_value = int(_data.get("TSI_DP14_SRCCTS_CTA_TIMING")[0])
            for _bit in _data.get("TSI_DP14_SRCCTS_CTA_TIMING")[1]:
                if cta_timing_value & int(_bit.mask):
                    configuration += "- {}<br>".format(_bit.description)

        if (int(_data.get("TSI_DP14_SRCCTS_DUT_CAPS")[1][17].mask) & int(
                _data.get("TSI_DP14_SRCCTS_DUT_CAPS")[0])) or \
                (int(_data.get("TSI_DP14_SRCCTS_DUT_CAPS")[1][18].mask) &
                 _data.get("TSI_DP14_SRCCTS_DUT_CAPS")[0]):
            configuration += "<br>CVT Timings:<br>"
            cvt_timing_value = int(_data.get("TSI_DP14_SRCCTS_CVT_TIMING")[0])
            for _bit in _data.get("TSI_DP14_SRCCTS_CVT_TIMING")[1]:
                if cvt_timing_value & int(_bit.mask):
                    configuration += "- {}<br>".format(_bit.description)

        configuration += "<br>Audio modes:<br>"

        for i in range(8):
            audio_mode = int(_data.get(f"TSI_DP14_SRCCTS_TESTED_AUDIO_MODE_{i}"))
            audio_type = ["Refer to Stream Header", "L-PCM", "AC-3", "MPEG-1", "MP3", "MPEG2", "AAC LC", "DTS",
                          "ATRAC", "One Bit Audio", "Enhanced AC-3", "DTS-HD", "MAT", "DST", "WMA Pro",
                          "Refer to Audio Coding Extension Type (CXT)"]
            audio_sampling = ["Refer to Stream Header", "32 kHz", "44.1 kHz (CD)", "48 kHz", "88.2 kHz", "96 kHz",
                              "176.4 kHz", "192 kHz"]
            audio_ch_count = ["Refer to Stream Header", "2 channels", "3 channels", "4 channels", "5 channels",
                              "6 channels", "7 channels", "8 channels"]
            audio_sample_size = ["Refer to Stream Header", "16 bit", "20 bit", "24 bit"]

            if audio_mode:
                configuration += "- Audio Mode {}: {}, {}, {} @ {}<br>".format(i, audio_type[
                    audio_mode >> 4 & 0xF],
                                                                               audio_ch_count[
                                                                                   audio_mode & 0x7],
                                                                               audio_sample_size[
                                                                                   audio_mode >> 8 & 0x3],
                                                                               audio_sampling[
                                                                                   audio_mode >> 10 & 0x7])
            else:
                configuration += f"- Audio Mode {i}: Disabled<br>"

        configuration += "<br>AdaptiveSync configuration:<br>"
        as_value = _data.get("TSI_DP14_SRCCTS_AS_DUT_CAPS")[0]
        for _bit in _data.get("TSI_DP14_SRCCTS_AS_DUT_CAPS")[1]:
            if as_value & _bit.mask:
                configuration += "- {}<br>".format(_bit.description)

        configuration += "- Adaptive-Sync range minimum refresh rate supported by the Source: {}<br>" \
            .format(value_from_enumeration_var(_data.get("TSI_DP14_SRCCTS_AS_RANGE_MIN_RATE")[1],
                                               _data.get("TSI_DP14_SRCCTS_AS_RANGE_MIN_RATE")[0]))

        as_timings = ["1920x1080p", "2560x1080p", "2560x1440p", "3840x2160p", "4096x2160p", "5120x2160p",
                      "7680x4320p", "10240x4320p"]

        for item in enumerate(as_timings):
            as_value = int(_data.get(f"TSI_DP14_SRCCTS_AS_RANGE_MAX_RATE_{item[0]}"))
            if as_value:
                configuration += "- {} maximum refresh rate: {}Hz<br>".format(item[1], as_value)
            else:
                configuration += "- {} is not supported<br>".format(item[1])

    elif type_of_test == TestReportConfigType.Dp2_1_Source:

        val = _data.get("TSI_DP20_SRCCTS_DUT_DEBUG_CONF")
        if val is not None and val[0] != 0:
            configuration += "<span class=DBG_HIGHLIGHT><br>Debug options:<br>"
            for _bit in val[1]:
                if val[0] & _bit.mask:
                    configuration += f" - {_bit.description}<br>"
            configuration += "<br>"

        configuration += "Test timeout = {}ms<br>".format(_data.get("TSI_DP20_SRCCTS_TIMEOUT"))
        configuration += "Long HPD Duration = {}ms<br><br>".format(_data.get("TSI_DP20_SRCCTS_LONG_HPD_PULSE"))
        configuration += "DUT capability settings and flags:<br>"
        configuration += "- Max lanes = {}<br>".format(_data.get("TSI_DP20_SRCCTS_MAX_LANES")[0])
        configuration += "- Max link rate = {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_MAX_LINK_RATE")[1],
                                       _data.get("TSI_DP20_SRCCTS_MAX_LINK_RATE")[0]))

        dut_caps_value = _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[0]
        for _bit in _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[1]:
            if dut_caps_value & _bit.mask:
                configuration += "- {}<br>".format(_bit.description)

        dut_link_rates_value = _data.get("TSI_DP20_SRCCTS_DUT_LINK_RATES")[0]
        for _bit in _data.get("TSI_DP20_SRCCTS_DUT_LINK_RATES")[1]:
            if dut_link_rates_value & _bit.mask:
                configuration += "- {}<br>".format(_bit.description)

        configuration += f"- Number of LTTPR devices: {_data.get('TSI_DP20_SRCCTS_LTTPR_DEVICE_COUNT')}<br>"
        configuration += "- Number of minimum link bandwidth: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_MAX_LINK_BW_POLICY")[1],
                                       _data.get("TSI_DP20_SRCCTS_MAX_LINK_BW_POLICY")[0]))

        configuration += "<br>Settings for Dynamic Refresh Rate with VBlank stretch with MSA_TIMING_PAR_IGNORED:<br>"
        configuration += f"- HActive: {_data.get('TSI_DP20_SRCCTS_DRR_HACTIVE')} pixels<br>"
        configuration += f"- VActive: {_data.get('TSI_DP20_SRCCTS_DRR_VACTIVE')} lines<br>"
        configuration += f"- Pixel Clock: {_data.get('TSI_DP20_SRCCTS_DRR_PIXEL_CLOCK')} kHz<br>"
        configuration += f"- Minimum Vertical Refresh Rate: {_data.get('TSI_DP20_SRCCTS_DRR_MIN_VRR')} Hz<br>"
        configuration += f"- Maximum Vertical Refresh Rate: {_data.get('TSI_DP20_SRCCTS_DRR_MAX_VRR')} Hz<br>"
        
        configuration += "<br>Test automation flags and settings:<br>"

        ta_flags = ["Always ready", "EDID read", "Link Training end", "Active Video"]
        ta_flags_value = _data.get("TSI_DP20_SRCCTS_DUT_TA")[0]
        for bit in _data.get("TSI_DP20_SRCCTS_DUT_TA")[1]:
            if bit.mask & ta_flags_value or bit.enumeration_variants is not None:
                if bit.enumeration_variants is not None:
                    configuration += "- Event indicating DUT ready: {}<br>".format(ta_flags[(ta_flags_value >> 3) & 0x3])
                else:
                    configuration += "- {}<br>".format(bit.description)

        configuration += "<br>Audio format:<br>"
        configuration += "- Minimum supported sample frequency: {}Hz<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_MIN_SAMPLE_RATE")[1],
                                       _data.get("TSI_DP20_SRCCTS_MIN_SAMPLE_RATE")[0]))
        configuration += "- Maximum supported sample frequency: {}Hz<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_MAX_SAMPLE_RATE")[1],
                                       _data.get("TSI_DP20_SRCCTS_MAX_SAMPLE_RATE")[0]))
        configuration += "- Audio test pattern: {}<br>". \
            format(value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_AUDIO_TEST_PATTERN")[1],
                                              _data.get("TSI_DP20_SRCCTS_AUDIO_TEST_PATTERN")[0]))
        configuration += "- Audio sample size: {}<br>". \
            format(value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_EDID_SAMPLE_SIZE")[1],
                                              _data.get("TSI_DP20_SRCCTS_EDID_SAMPLE_SIZE")[0]))

        ch_alloc_title = ["Minimum channel configuration / Min. sample rate",
                          "Maximum channel configuration / Min. sample rate",
                          "Minimum channel configuration / Max. sample rate",
                          "Maximum channel configuration / Max. sample rate"]

        ch_alloc_str = [
            "- Front Left + Front Right (2 Channels)",
            "- Low Frequency Effect (1 Channel)",
            "- Front Center (1 Channel)",
            "- Rear Left + Rear Right (2 Channels)",
            "- Rear Center (1 Channel)",
            "- Front Left Center + Front Right Center (2 Channels)",
            "- Rear Left Center + Rear Right Center (2 Channels)",
            "- Front Left Wide + Front Right Wide (2 Channels)",
            "- Front Left High + Front Right High (2 Channels)",
            "- Top Center (1 Channel)",
            "- Front Center High (1 Channel)"]

        for i in range(len(ch_alloc_title)):
            CH_ALLOC_CI = f"TSI_DP20_SRCCTS_CH_ALLOC{i + 1}"
            CH_ALLOC_VAL = int(_data.get(CH_ALLOC_CI))

            CH_COUNT_CI = f"TSI_DP20_SRCCTS_CHANNELS{i + 1}"
            CH_COUNT_VAL = int(_data.get(CH_COUNT_CI))

            configuration += "<br>{}:<br>".format(ch_alloc_title[i])
            configuration += "- Channel count: {}<br>".format(CH_COUNT_VAL)

            for j in range(len(ch_alloc_str)):
                if CH_ALLOC_VAL >> j & 1:
                    configuration += "{}<br>".format(ch_alloc_str[j])

        configuration += "<br>DSC Info:<br>"
        dsc_version = int(_data.get("TSI_DP20_SRCCTS_DSC_VERSION")[0])
        configuration += "- DSC Version: {}.{}<br>".format((dsc_version >> 16) & 0xff, dsc_version & 0xff)
        configuration += "- DSC Max. Slices: {}<br>".format(
            value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_DSC_DUT_MAX_SLICE")[1],
                                       _data.get("TSI_DP20_SRCCTS_DSC_DUT_MAX_SLICE")[0]))

        configuration += "<br>DisplayID test configuration:<br>"
        configuration += "- Max HActive = {}<br>".format(_data.get("TSI_DP20_SRCCTS_MAX_STREAM_HACTIVE"))
        configuration += "- Max VActive = {}<br>".format(_data.get("TSI_DP20_SRCCTS_MAX_STREAM_VACTIVE"))
        configuration += "- Max Pixel Clock (kHz) = {} <br>".format(
            _data.get("TSI_DP20_SRCCTS_MAX_STREAM_PIXEL_CLOCK"))

        if _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[1][17].mask & _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[0]:
            configuration += "<br>DMT Timings:<br>"
            dmt_timing_value = _data.get("TSI_DP20_SRCCTS_DMT_TIMING")[0]
            for _bit in _data.get("TSI_DP20_SRCCTS_DMT_TIMING")[1]:
                if dmt_timing_value & _bit.mask:
                    configuration += "- {}<br>".format(_bit.description)

        if _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[1][18].mask & _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[0]:
            configuration += "<br>CTA Timings:<br>"
            cta_timing_value = _data.get("TSI_DP20_SRCCTS_CTA_TIMING")[0]
            for _bit in _data.get("TSI_DP20_SRCCTS_CTA_TIMING")[1]:
                if cta_timing_value & _bit.mask:
                    configuration += "- {}<br>".format(_bit.description)

        if (_data.get("TSI_DP20_SRCCTS_DUT_CAPS")[1][19].mask & _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[0]) or \
                (_data.get("TSI_DP20_SRCCTS_DUT_CAPS")[1][20].mask & _data.get("TSI_DP20_SRCCTS_DUT_CAPS")[0]):
            configuration += "<br>CVT Timings:<br>"
            cvt_timing_value = _data.get("TSI_DP20_SRCCTS_CVT_TIMING")[0]
            for _bit in _data.get("TSI_DP20_SRCCTS_CVT_TIMING")[1]:
                if cvt_timing_value & _bit.mask:
                    configuration += "- {}<br>".format(_bit.description)

        configuration += "<br>Audio modes:<br>"

        for i in range(8):
            audio_mode = int(_data.get(f"TSI_DP20_SRCCTS_TESTED_AUDIO_MODE_{i}"))
            audio_type = ["Refer to Stream Header", "L-PCM", "AC-3", "MPEG-1", "MP3", "MPEG2", "AAC LC", "DTS",
                          "ATRAC", "One Bit Audio", "Enhanced AC-3", "DTS-HD", "MAT", "DST", "WMA Pro",
                          "Refer to Audio Coding Extension Type (CXT)"]
            audio_sampling = ["Refer to Stream Header", "32 kHz", "44.1 kHz (CD)", "48 kHz", "88.2 kHz", "96 kHz",
                              "176.4 kHz", "192 kHz"]
            audio_ch_count = ["Refer to Stream Header", "2 channels", "3 channels", "4 channels", "5 channels",
                              "6 channels", "7 channels", "8 channels"]
            audio_sample_size = ["Refer to Stream Header", "16 bit", "20 bit", "24 bit"]

            if audio_mode:
                configuration += "- Audio Mode {}: {}, {}, {} @ {}<br>".format(i, audio_type[
                    audio_mode >> 4 & 0xF],
                                                                               audio_ch_count[
                                                                                   audio_mode & 0x7],
                                                                               audio_sample_size[
                                                                                   audio_mode >> 8 & 0x3],
                                                                               audio_sampling[
                                                                                   audio_mode >> 10 & 0x7])
            else:
                configuration += f"- Audio Mode {i}: Disabled<br>"

        configuration += "<br>AdaptiveSync configuration:<br>"
        as_value = _data.get("TSI_DP20_SRCCTS_AS_DUT_CAPS")[0]
        for _bit in _data.get("TSI_DP20_SRCCTS_AS_DUT_CAPS")[1]:
            if as_value & _bit.mask:
                configuration += "- {}<br>".format(_bit.description)

        configuration += "- Adaptive-Sync range minimum refresh rate supported by the Source: {}<br>" \
            .format(value_from_enumeration_var(_data.get("TSI_DP20_SRCCTS_AS_RANGE_MIN_RATE")[1],
                                               _data.get("TSI_DP20_SRCCTS_AS_RANGE_MIN_RATE")[0]))

        as_timings = ["1920x1080p", "2560x1080p", "2560x1440p", "3840x2160p", "4096x2160p", "5120x2160p",
                      "7680x4320p", "10240x4320p"]

        for item in enumerate(as_timings):
            as_value = int(_data.get(f"TSI_DP20_SRCCTS_AS_RANGE_MAX_RATE_{item[0]}"))
            if as_value:
                configuration += "- {} maximum refresh rate: {}Hz<br>".format(item[1], as_value)
            else:
                configuration += "- {} is not supported<br>".format(item[1])

        colorimetry_map = {0: '-', 1: 8, 3: 10, 7: 12, 15: 16}

        def add_column_title(include_dsc : bool):
            title = "<tr>"
            style = 'style="padding: 10px; border: 1px solid black;"'
            title_list = [f'<th rowspan="2" {style}>Timing</th>\n',
                          f'<th colspan="6" {style}>Timing vendors</th>\n',
                          f'<th colspan="5" {style}>Colorimetry</th>\n']
            timing_vendors = ['CTA', 'DMT', 'CVT', 'CVT RB1', 'CVT RB2', 'OVT']
            colorimetry = ["RGB", "YCbCr444", "YCbCr422", "YCbCr422Simple", "YCbCr420"] if include_dsc else [ "RGB", "YCbCr444", "YCbCr422", "YCbCr420" ]

            for title_item in title_list:
                title += title_item
            title += "</tr>\n<tr>"

            for timing_vendors_item in timing_vendors:
                title += f'<th {style}>{timing_vendors_item}</th>'

            for colorimetry_item in colorimetry:
                title += f'<th {style}>{colorimetry_item}</th>'

            title += "</tr>\n"

            return title

        def add_video_row(timing_info, tim_value):
            style = 'align="center";'
            row = f'<tr><td align="left">{timing_info}</td>' \
                  f'<td {style}>{"+" if tim_value & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 1) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 2) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 3) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 4) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 5) & 0x1 else "-"}</td>'
            row += f'<td {style}>{colorimetry_map.get((tim_value >> 12) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 16) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 20) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 28) & 0xF)}</td>'
            return row

        def add_dsc_row(timing_info, tim_value):
            style = 'align="center";'
            row = f'<tr><td align="left">{timing_info}</td>' \
                  f'<td {style}>{"+" if tim_value & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 1) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 2) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 3) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 4) & 0x1 else "-"}</td>' \
                  f'<td {style}>{"+" if (tim_value >> 5) & 0x1 else "-"}</td>'
            row += f'<td {style}>{colorimetry_map.get((tim_value >> 12) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 16) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 20) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 24) & 0xF)}</td>' \
                   f'<td {style}>{colorimetry_map.get((tim_value >> 28) & 0xF)}</td>'
            return row

        configuration += '<br><table border="1">' + add_column_title(False)

        deprecated_video_modes = [ "TSI_DP20_SRCCTS_VMT_1920_1080_144", "TSI_DP20_SRCCTS_VMT_1920_1080_240",
                                   "TSI_DP20_SRCCTS_VMT_3840_2160_30", "TSI_DP20_SRCCTS_VMT_3840_2160_240",
                                   "TSI_DP20_SRCCTS_VMT_5120_2160_120", "TSI_DP20_SRCCTS_VMT_5120_2160_240",
                                   "TSI_DP20_SRCCTS_VMT_7680_4320_120", "TSI_DP20_SRCCTS_VMT_10240_4320_30",
                                   "TSI_DP20_SRCCTS_VMT_10240_4320_60"]

        for key in _data.keys():
            if key in deprecated_video_modes:
                continue
            if key.find("TSI_DP20_SRCCTS_VMT_") != -1:
                value = _data.get(key)
                _, h_active, w_active, rate = re.findall(r'\d+', key)
                configuration += add_video_row(f"{h_active}x{w_active} @ {rate}Hz", value)
        configuration += "</table><br>"

        configuration += '<br><table border="1">' + add_column_title(True)

        for key in _data.keys():
            if key.find("TSI_DP20_SRCCTS_DSC_VMT_") != -1:
                value = _data.get(key)
                _, h_active, w_active, rate = re.findall(r'\d+', key)
                configuration += add_dsc_row(f"{h_active}x{w_active} @ {rate}Hz", value)
        configuration += "</table><br>"


    elif type_of_test == TestReportConfigType.Dp1_4_Sink:
        configuration = "Test timeout = {}ms<br>".format(_data.get("TSI_DP14_SINKCTS_TIMEOUT"))
        if not int(_data.get("TSI_DP14_SINKCTS_DSC_SOURCE")[0]):
            configuration += "<br>DSC resolutions to be tested:<br>"
            dsc_timings = ["1920x1080 @ 30Hz", "1920x1080 @ 60Hz", "1920x1080 @ 120Hz", "3840x2160 @ 30Hz",
                           "3840x2160 @ 60Hz", "3840x2160 @ 120Hz", "5120x2160 @ 30Hz", "5120x2160 @ 60Hz",
                           "5120x2160 @ 120Hz", "7680x4320 @ 30Hz", "7680x4320 @ 60Hz", "7680x4320 @ 100Hz"]

            for item in enumerate(dsc_timings):
                timing_flags = int(str(_data.get(f"TSI_DP14_SINKCTS_DSC_VM_T_{item[0]}")), 16)
                if timing_flags:
                    configuration += "- {}{}{}{}<br>".format(item[1], " CTA" if timing_flags & 0x1 else "",
                                                             " RB1" if timing_flags & 0x2 else "",
                                                             " RB2" if timing_flags & 0x4 else "")
        else:
            configuration += "<br>DSC resolutions to be tested are defined by DUT EDID<br>"

        configuration += "<br>Sink DUT supports DSC Simple 422 CRC for {}<br>". \
            format(value_from_enumeration_var(_data.get("TSI_DP14_SINKCTS_SUPPORT_444CRC")[1],
                                              _data.get("TSI_DP14_SINKCTS_SUPPORT_444CRC")[0]))

        if int(_data.get("TSI_DP14_SINKCTS_VISUAL_TEST_CHECK")[0]):
            configuration += "Never skip Display ID test's visual video checks<br>"
        else:
            configuration += "Skip Display ID test's visual video checks if CRC available and matching<br>"

        if not int(_data.get("TSI_DP14_SINKCTS_PACKET_SOURCE")[0]):
            configuration += "<br>Most packed resolutions to be tested:<br>"
            video_timings = ["CVT 1280 x 800 @ 60p [RB1] 18bpp 99", "DMT 1280 x 768 @ 60p [RB1] 18bpp 95",
                             "DMT 800 x 600 @ 60.317p 30bpp 93", "DMT 1024 x 768 @ 60p 18bpp 90",
                             "DMT 1280 x 1024 @ 60p 24bpp 100", "DMT 1280 x 960 @ 60p 24bpp 100",
                             "DMT 1360 x 768 @ 60p 30bpp 99", "CVT 1280 x 800 @ 60p 30bpp 97",
                             "DMT 1400 x 1050 @ 60p [RB1] 24bpp 94", "DMT 1280 x 768 @ 60p 30bpp 92",
                             "CVT 1600 x 1200 @ 60p [RB1] 18bpp 90", "CVT 2048 x 1536 @ 60p [RB1] 24bpp 97",
                             "DMT 1792 x 1344 @ 60p 24bpp 95", "DMT 1600 x 1200 @ 60p 30bpp 94",
                             "CTA 1440 x 480 @ 59.94p 24bpp 100", "CTA 1440 x 576 @ 50p 24bpp 100",
                             "CTA 1920 x 1080 @ 60p 30bpp 86"]

            for item in video_timings:
                configuration += "- {}<br>".format(item)
        else:
            configuration += "<br>Most packed resolutions to be tested are defined by DUT EDID<br>"
    elif type_of_test == TestReportConfigType.Dp2_1_Sink:
        configuration = ""

        val = _data.get("TSI_DP20_SINKCTS_DEBUG_CONF")
        if val is not None and val[0] != 0:
            configuration += "<span class=DBG_HIGHLIGHT><br>Debug options:<br>"
            for _bit in val[1]:
                if val[0] & _bit.mask:
                    configuration += f" - {_bit.description}<br>"
            configuration += "<br>"

        configuration += "Test timeout = {}ms<br>".format(_data.get("TSI_DP20_SINKCTS_TIMEOUT"))
        if not int(_data.get("TSI_DP20_SINKCTS_DSC_SOURCE")[0]):
            configuration += "<br>DSC resolutions to be tested:<br>"
            video_modes_list = [[1920, 1080, 30], [1920, 1080, 60], [1920, 1080, 120], [1920, 1080, 144],
                                [1920, 1080, 240],
                                [3840, 2160, 30], [3840, 2160, 60], [3840, 2160, 120], [3840, 2160, 144],
                                [3840, 2160, 240],
                                [5120, 2160, 30], [5120, 2160, 60], [5120, 2160, 120], [5120, 2160, 144],
                                [5120, 2160, 240],
                                [7680, 4320, 30], [7680, 4320, 60], [7680, 4320, 120], [7680, 4320, 144],
                                [7680, 4320, 240],
                                [10240, 4320, 30], [10240, 4320, 60], [10240, 4320, 120], [10240, 4320, 144],
                                [10240, 4320, 240],
                                [15360, 8640, 30], [15360, 8640, 60], [15360, 8640, 120], [15360, 8640, 144],
                                [15360, 8640, 240]]
            for vm in video_modes_list:
                timing_flag = _data.get(f"TSI_DP20_SINKCTS_VMT_{vm[0]}_{vm[1]}")
                bit_n = 0
                if vm[2] == 60:
                    bit_n = 4
                elif vm[2] == 120:
                    bit_n = 8
                elif vm[2] == 144:
                    bit_n = 13
                elif vm[2] == 240:
                    bit_n = 17

                if vm[2] in [144, 240]:
                    rb1_value = (timing_flag >> bit_n) & 0x1
                    rb2_value = (timing_flag >> (bit_n + 1)) & 0x1
                    ovt_value = (timing_flag >> (bit_n + 2)) & 0x1
                    if rb1_value or rb2_value or ovt_value:
                        configuration += f"- {vm[0]}x{vm[1]} @ {vm[2]}Hz" \
                                         f"{' RB1' if rb1_value else ''}" \
                                         f"{' RB2' if rb2_value else ''}" \
                                         f"{' OVT' if ovt_value else ''}<br>"
                else:
                    cta_value = (timing_flag >> bit_n) & 0x1
                    rb1_value = (timing_flag >> (bit_n + 1)) & 0x1
                    rb2_value = (timing_flag >> (bit_n + 2)) & 0x1
                    if rb1_value or rb2_value or cta_value:
                        configuration += f"- {vm[0]}x{vm[1]} @ {vm[2]}Hz" \
                                         f"{' CTA' if cta_value else ''}" \
                                         f"{' RB1' if rb1_value else ''}" \
                                         f"{' RB2' if rb2_value else ''}<br>"
        else:
            configuration += "<br>DSC resolutions to be tested are defined by DUT EDID<br>"

        if _data.get("TSI_DP20_SINKCTS_SUPPORT_444CRC")[0] == 0:
            configuration += "<br>Sink DUT supports YCbCR 422 CRC for Simple 422 bitstream<br>"
        elif _data.get("TSI_DP20_SINKCTS_SUPPORT_444CRC")[0] == 1:
            configuration += "<br>Sink DUT supports YCbCR 444 CRC for Simple 422 bitstream<br>"
        else:
            configuration += "<br><br>"

        if int(_data.get("TSI_DP20_SINKCTS_VISUAL_TEST_CHECK")[0]):
            configuration += "<br>Skip Display ID test's visual video checks if CRC available and matching<br>"
        else:
            configuration += "<br>Never skip Display ID test's visual video checks<br>"

    return configuration


def dp21_source_timing_table(data) -> str:
    _data = copy_data(data)
    colorimetry_map = {0: '-', 1: 8, 3: 10, 7: 12, 15: 16}
    info = f"Timing {'Timing vendors':>35} {'Colorimetry':>40}\n"
    info += f"{'CTA DMT CVT CVT-RB1 CVT-RB2 OVT':>50}"
    info += f"{'RGB YCbCr444 YCbCr422 YCbCr422Simple YCbCr420':>50}\n"

    def shift(str_length) -> int:
        if str_length == 14:
            return 7
        elif str_length == 15:
            return 6
        elif str_length == 16:
            return 5
        elif str_length == 17:
            return 4

    def support(flag) -> str:
        return "+" if flag else "-"

    def add_row(timing_info, tim_value):
        row = f'{timing_info}' \
              f'{support(tim_value & 0x1):>{shift(len(timing_info))}}' \
              f'{support((tim_value >> 1) & 0x1):>4}' \
              f'{support((tim_value >> 2) & 0x1):>4}' \
              f'{support((tim_value >> 3) & 0x1):>6}' \
              f'{support((tim_value >> 4) & 0x1):>8}' \
              f'{support((tim_value >> 5) & 0x1):>6}'
        row += f'{colorimetry_map.get((tim_value >> 12) & 0xF):>8}' \
               f'{colorimetry_map.get((tim_value >> 16) & 0xF):>7}' \
               f'{colorimetry_map.get((tim_value >> 20) & 0xF):>9}' \
               f'{colorimetry_map.get((tim_value >> 24) & 0xF):>12}' \
               f'{colorimetry_map.get((tim_value >> 28) & 0xF):>12}\n'
        return row

    for key in _data.keys():
        if key.find("TSI_DP20_SRCCTS_VMT_") != -1:
            value = _data.get(key)
            _, h_active, w_active, rate = re.findall(r'\d+', key)
            info += add_row(f"{h_active}x{w_active} @ {rate}Hz", value)

    return info
