#!/usr/bin/python
# vpn.py: a top level interface to commands to run VPNs on a VM as
# different clients. The use case is allowing us to measure from more
# places.

import argparse
import logging
from random import shuffle
import os
import time
import sys
import signal
import dns.resolver
import json

import centinel.backend
import centinel.client
import centinel.config
import centinel.vpn.openvpn as openvpn
import centinel.vpn.hma as hma
import centinel.vpn.ipvanish as ipvanish
import centinel.vpn.purevpn as purevpn
import centinel.vpn.vpngate as vpngate


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--auth-file', '-u', dest='auth_file', default=None,
                        help=("File with HMA username on first line, \n"
                              "HMA password on second line"))
    parser.add_argument('--crt-file', '-r', dest='crt_file', default=None,
                        help=("Certificate file for the current vpn\n"
                              "provider, if provided"))
    parser.add_argument('--tls-auth', '-t', dest='tls_auth', default=None,
                        help="Key for additional layer of authentication")
    parser.add_argument('--key-direction', '-k', dest='key_direction', default=None,
                        help=("Key direction for tls auth, must specify when "
                              "tls-auth is used"))
    parser.add_argument('--reduce-endpoint', dest='reduce_vp',
                        action="store_true", default=False,
                        help="Reduce the number of vantage points by only connect to "
                             "one vantage point for each AS and country combination")
    g1 = parser.add_mutually_exclusive_group()
    g1.add_argument('--create-hma-configs', dest='create_HMA',
                    action="store_true",
                    help='Create the openvpn config files for HMA')
    g1.add_argument('--create-ipvanish-configs', dest='create_IPVANISH',
                    action='store_true',
                    help='Create the openvpn config files for IPVanish')
    g1.add_argument('--create-purevpn-configs', dest='create_PUREVPN',
                    action='store_true',
                    help='Create the openvpn config files for PureVPN')
    g1.add_argument('--create-vpngate-configs', dest='create_VPNGATE',
                    action='store_true',
                    help='Create the openvpn config files for VPN Gate')
    parser.add_argument('--shuffle', '-s', dest='shuffle_lists',
                        action="store_true", default=False,
                        help='Randomize the order of vantage points')
    parser.add_argument('--exclude', '-e', dest='exclude_list', default=None,
                        help=('Countries to exclude when scanning (comma '
                              'separated two letter country codes)'))
    parser.add_argument('--log-file', '-l', dest='log_file', default=None,
                        help="Log file location")
    g2 = parser.add_mutually_exclusive_group(required=True)
    g2.add_argument('--directory', '-d', dest='directory',
                    help='Directory with experiments, config files, etc.')
    create_conf_help = ('Create configuration files for the given '
                        'openvpn config files so that we can treat each '
                        'one as a client. The argument should be a '
                        'directory with a subdirectory called openvpn '
                        'that contains the openvpn config files')
    g2.add_argument('--create-config', '-c', help=create_conf_help,
                    dest='create_conf_dir')

    # following args are used to support splitting clients among multiple VMs
    # each running vpn walker will use this to decide which portion of vpn
    # endpoints it should include
    parser.add_argument('--vm-num', dest='vm_num', type=int, default=1,
                        help="Specify the number of VMs running concurrently")
    parser.add_argument('--vm-index', dest='vm_index', type=int, default=1,
                        help='The index of current VM, must be >= 1 and '
                             '<= vm_num')
    return parser.parse_args()


def scan_vpns(directory, auth_file, crt_file, tls_auth, key_direction,
              exclude_list, shuffle_lists, vm_num, vm_index, reduce_vp):
    """
    For each VPN, check if there are experiments and scan with it if
    necessary

    Note: the expected directory structure is
    args.directory
    -----vpns (contains the OpenVPN config files
    -----configs (contains the Centinel config files)
    -----exps (contains the experiments directories)

    :param directory: root directory that contains vpn configs and
                      centinel client configs
    :param auth_file: a text file with username at first line and
                      password at second line
    :param crt_file: optional root certificate file
    :param tls_auth: additional key
    :param key_direction: must specify if tls_auth is used
    :param exclude_list: optional list of exluded countries
    :param shuffle_lists: shuffle vpn list if set true
    :param vm_num: number of VMs that are running currently
    :param vm_index: index of current VM