import re


def parse_show_spanning_tree(raw_result):
    """
    Parse the 'show spanning-tree' command raw output.

    :param str raw_result: vtysh raw result string.
    :rtype: dict
    :return: The parsed result of the show spanning-tree \
       command in a dictionary of the form:

     ::

        {
            'spanning_tree': 'Enabled',
            'root': 'yes',
            'root_priority': '10',
            'root_mac_address': '70:72:cf:3e:b7:27',
            'root_hello': '4',
            'root_max_age': '17',
            'root_forward_delay': '14',
            'bridge_mac_address': '70:72:cf:3e:b7:27',
            'bridge_priority': '10',
            'bridge_hello': '4',
            'bridge_max_age': '17',
            'bridge_forward_delay': '14',
            '1':
            {
                   'priority': '8',
                   'cost': '0',
                   'type': 'point_to_point',
                   'role': 'disabled_port',
                   'State': 'Blocking'
            },
            '2':
            {
                   'priority': '8',
                   'cost': '0',
                   'type': 'point_to_point',
                   'role': 'disabled_port',
                   'State': 'Blocking'
            },
            'error' : 'No MSTP common instance record found'
        }
    """

    mst_zero_config = (
        r'\s*Spanning\s*tree\s*status:\s*(?P<spanning_tree>.+)\s*\n'
        r'\s*Root\s*ID\s*Priority\s*:\s*(?P<root_priority>[0-9]*)\s*\n'
        r'\s*MAC-Address\s*:\s*(?P<root_mac_address>[^ ]*)\s*\n'
        r'\s*Hello\s*time\(in\s*seconds\):\s*(?P<root_hello>[0-9]+)'
        r'\s*Max\s*Age\(in\s*seconds\):\s*(?P<root_max_age>[0-9]+)'
        r'\s*Forward\s*Delay\(in\s*seconds\):(?P<root_forward_delay>[0-9]+)'
        r'\s*\n*'
        r'\s*Bridge\s*ID \s*Priority\s*:\s*(?P<bridge_priority>[0-9]*)\s*\n'
        r'\s*MAC-Address\s*:\s*(?P<bridge_mac_address>[^ ]+)\s*\n'
        r'\s*Hello\s*time\(in\s*seconds\):\s*(?P<bridge_hello>[0-9]+)'
        r'\s*Max\s*Age\(in\s*seconds\):\s*(?P<bridge_max_age>[0-9]+)'
        r'\s*Forward\s*Delay\(in\s*seconds\):(?P<bridge_forward_delay>[0-9]+)'
    )

    mst_port_state = (
        r'(?P<Port>[^ ]+)\s*(?P<role>[^ ]+)\s*(?P<State>[^ ]+)'
        r'\s*(?P<cost>[0-9]+)\s*(?P<priority>[0-9]+)\s*(?P<type>[^ ]+)'
    )

    error = [
        r'No\s*MSTP\s*common\s*instance\s*record\s*found',
        r'No\s*record\s*found\.',
        r'\s*Spanning-tree\s*is\s*disabled'
    ]

    result = {}
    for error_str in error:
        re_result = re.search(error_str, raw_result)

        if (re_result):
            result['error'] = str(raw_result)
            return result

    root = False
    if 'This bridge is the root' in raw_result:
        raw_result = re.sub(r'\s*This\s*bridge\s*is\s*the\s*root\s*\n', '\n',
                            raw_result, 1)
        root = True

    re_result = re.search(mst_zero_config, raw_result)
    assert re_result

    result = re_result.groupdict()

    result['root'] = 'no'
    if root:
        result['root'] = 'yes'

    pattern_found = False
    for line in raw_result.splitlines():
        if (pattern_found is True):
            re_result = re.search(mst_port_state, line)
            if re_result:
                partial = re_result.groupdict()
                port = partial['Port']
                del partial['Port']
                result[port] = partial
        else:
            re_result = re.search('-+\s*-+', line)
            if (re_result):
                pattern_found = True

    return result