import re


def default_output_mixer_channel(discovery_props, output_channel=0):
    """Return an instrument's default output mixer channel based on the specified
    `devicetype` and `options` discovery properties and the hardware output
    channel.

    This utility function is used by the ziPython examples and returns a node
    available under the /devX/sigouts/0/{amplitudes,enables}/ branches.

    Args:

      discovery_props (dict): A device's discovery properties as returned by
        ziDiscovery's get() method.

      output_channel (int, optional): The zero-based index of the hardware
        output channel for which to return an output mixer channel.

    Returns:

      output_mixer_channel (int): The zero-based index of an available signal
      output mixer channel.

    Raises:

      Exception: If an invalid signal input index was provided.

    """

    # The logic below assumes the device type is one of the following.
    assert discovery_props['devicetype'] in ['HF2IS', 'HF2LI', 'UHFLI', 'UHFAWG', 'UHFQA', 'MFIA', 'MFLI'], \
        "Unknown device type: {}.".format(discovery_props['devicetype'])

    if re.match('UHF', discovery_props['devicetype']) and ('MF' not in discovery_props['options']):
        if output_channel == 0:
            output_mixer_channel = 3
        elif output_channel == 1:
            output_mixer_channel = 7
        else:
            raise Exception("Invalid output channel `{}`, UHF Instruments have two signal "
                            "ouput channels (0, 1).".format(output_channel))
    elif re.match('HF2LI', discovery_props['devicetype']) and ('MF' not in discovery_props['options']):
        if output_channel == 0:
            output_mixer_channel = 6
        elif output_channel == 1:
            output_mixer_channel = 7
        else:
            raise Exception("Invalid output channel `{}`, HF2 Instruments have two signal output"
                            "channels (0, 1).".format(output_channel))
    elif re.match('(MFLI|MFIA)', discovery_props['devicetype']) and ('MD' not in discovery_props['options']):
        if output_channel == 0:
            output_mixer_channel = 1
        else:
            raise Exception("Invalid output channel `{}`, MF Instruments have one signal output channel (0)."
                            .format(output_channel))
    else:
        output_mixer_channel = 0
    return output_mixer_channel