#!/usr/bin/env python
# Copyright 2024 Google LLC
#
# 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 sys
import glob


def _is_accessory(tty_type):
    return tty_type is "accessory"


def _get_linux_tty(ttys, tty_type):
    for t in ttys:
        import sh

        cmd_stdout = sh.udevadm('info', query='property', name=t)
        # Build our dictionary of the tty values. The output looks something like this:
        #
        # DEVLINKS=/dev/serial/by-id/usb-FTDI_Quad_RS232-HS-if01-port0 /dev/serial/by-path/pci-0000:00:1d.0-usb-0:1.5.3:1.1-port0
        # DEVNAME=/dev/ttyUSB1
        # DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5/2-1.5.3/2-1.5.3:1.1/ttyUSB1/tty/ttyUSB1
        # ID_BUS=usb
        # ID_MM_CANDIDATE=1
        # ID_MODEL=Quad_RS232-HS
        # ID_MODEL_ENC=Quad\x20RS232-HS
        # ID_MODEL_FROM_DATABASE=FT4232H Quad HS USB-UART/FIFO IC
        # ...
        tty_properties = {}
        for line in cmd_stdout.splitlines():
            name, value = line.split('=')
            tty_properties[name] = value

        if tty_properties['ID_MODEL'] == 'Quad_RS232-HS':
            # snowy_bb2 uses interface 02 (0 indexed out of 4) for dbgserial
            if not _is_accessory(tty_type) and tty_properties['ID_USB_INTERFACE_NUM'] == '02':
                return t
            if _is_accessory(tty_type) and tty_properties['ID_USB_INTERFACE_NUM'] == '03':
                return t
        elif tty_properties['ID_MODEL'] == 'Dual_RS232-HS':
            # bb2 uses interface 01 (0 indexed out of 2) for dbgserial
            if not _is_accessory(tty_type) and tty_properties['ID_USB_INTERFACE_NUM'] == '01':
                return t

    # We didn't find anything?
    return None


def _get_mac_tty(ttys, tty_type):
    tty_b = tty_c = tty_d = tty_slab = None
    for path in ttys:
        if path.endswith('B'):
            tty_b = path
        if path.endswith('C'):
            tty_c = path
        if path.endswith('D'):
            tty_d = path
        if path.endswith('SLAB_USBtoUART'):
            tty_slab = path

    # if we find C or D, we're on a snowy bb2
    if tty_c is not None and not _is_accessory(tty_type):
        return tty_c
    if tty_d is not None and _is_accessory(tty_type):
        return tty_d
    # we're talking to tintin
    if tty_b is not None and not tty_c and not _is_accessory(tty_type):
        return tty_b

    if tty_slab is not None and not _is_accessory(tty_type):
        return tty_slab

    return None


def _find_all_ttys():
    pattern = None
    if sys.platform == 'darwin':
        pattern = '/dev/cu.*[uU][sS][bB]*'
    elif sys.platform == 'linux2':
        pattern = '/dev/ttyUSB*'
    else:
        raise Exception("No TTY auto-selection for this platform!")

    return glob.glob(pattern)


def _get_tty(tty_type="primary"):
    ttys = _find_all_ttys()
    if not ttys:
        return None

    if sys.platform == 'darwin':
        tty = _get_mac_tty(ttys, tty_type)
    elif sys.platform == 'linux2':
        tty = _get_linux_tty(ttys, tty_type)

    return tty