#!/usr/bin/env vpython3
#
# Copyright 2013 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Command line tool for forwarding ports from a device to the host.

Allows an Android device to connect to services running on the host machine,
i.e., "adb forward" in reverse. Requires |host_forwarder| and |device_forwarder|
to be built.
"""

import argparse
import sys
import time

import devil_chromium

from devil.android import device_denylist
from devil.android import device_utils
from devil.android import forwarder
from devil.utils import run_tests_helper

from pylib import constants


def main(argv):
    parser = argparse.ArgumentParser(
        usage='Usage: %(prog)s [options] device_port '
        'host_port [device_port_2 host_port_2] ...',
        description=__doc__,
    )
    parser.add_argument(
        '-v',
        '--verbose',
        dest='verbose_count',
        default=0,
        action='count',
        help='Verbose level (multiple times for more)',
    )
    parser.add_argument(
        '--device', help='Serial number of device we should use.'
    )
    parser.add_argument('--denylist-file', help='Device denylist JSON file.')
    parser.add_argument(
        '--debug',
        action='store_const',
        const='Debug',
        dest='build_type',
        default='Release',
        help='DEPRECATED: use --output-directory instead.',
    )
    parser.add_argument(
        '--output-directory', help='Path to the root build directory.'
    )
    parser.add_argument(
        'ports', nargs='+', type=int, help='Port pair to reverse forward.'
    )

    args = parser.parse_args(argv)
    run_tests_helper.SetLogLevel(args.verbose_count)

    if len(args.ports) < 2 or len(args.ports) % 2:
        parser.error('Need even number of port pairs')

    port_pairs = list(zip(args.ports[::2], args.ports[1::2]))

    if args.build_type:
        constants.SetBuildType(args.build_type)
    if args.output_directory:
        constants.SetOutputDirectory(args.output_directory)
    devil_chromium.Initialize(output_directory=constants.GetOutDirectory())

    denylist = (
        device_denylist.Denylist(args.denylist_file)
        if args.denylist_file
        else None
    )
    device = device_utils.DeviceUtils.HealthyDevices(
        denylist=denylist, device_arg=args.device
    )[0]
    try:
        forwarder.Forwarder.Map(port_pairs, device)
        while True:
            time.sleep(60)
    except KeyboardInterrupt:
        sys.exit(0)
    finally:
        forwarder.Forwarder.UnmapAllDevicePorts(device)


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
