#!/usr/bin/env python3

import argparse # accept commandline input
import keyring
import getpass
import sys
import subprocess
import time
import datetime
try:
    import httplib
except:
    import http.client as httplib

#configuration options
app_name = "vpnhelper"
vpn_name = "TDEV IPSec VPN"
update_interval = "5" #how often to check VPN (in seconds)
dayBegins = datetime.datetime.now().replace(hour=9, minute=0, second=0)
dayEnds =  datetime.datetime.now().replace(hour=18, minute=0, second=0)
lunchBegins = datetime.datetime.now().replace(hour=12, minute=0, second=0)
lunchEnds = datetime.datetime.now().replace(hour=13, minute=0, second=0)
clickspeed = {'superslow':2, 'slow':1, 'normal':1, 'fast':0.5, 'superfast':0.25}
defaults = {'fillpassword':'andReturn', 'duration':'fd', 'clickspeed':'normal', 'updatepass':'chrome', 'warning':'no'}
# Run for workday, fill in password, don't hit enter, use normal delays. If user wishes to update password, defaults to chrome.


def screenActive():
    """Returns False if screen is locked.  True otherwise."""
    
    #Should output 4 if screen is active on mac, 0 otherwise:
    code =  subprocess.call("ioreg -n IODisplayWrangler | grep -i IOPowerManagement | perl -pe 's/^.*DevicePowerState\"=([0-9]+).*$/\1/'".format( genAppleScript() ), shell=True)

    if code == 4:
       return True
    else:
        return false

def connectionResponsive():
    """Checks if it's possible to talk to google"""
    connection = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        connection.request("HEAD", "/")
        connection.close()
        return True
    except:
        connection.close()
        return False
    
def fetchCredentials():
    global username
    global password
    global vpn_name

    username = keyring.get_password(vpn_name, "username")
    if username == None:
        raise
    password = keyring.get_password(vpn_name, "password")
    
def resetCredentials():
    global username
    global password

    username = input("Please supply the vpn username:")
    password = getpass.getpass("Please supply the vpn password:")
    keyring.set_password(vpn_name, "username", username)
    keyring.set_password(vpn_name, "password", password)

def setVpnName():
    global vpn_name
    global args

    #Get VPN Name
    if args.vpn != None:
        vpn_name = args.vpn
        print("VPN name set to {}. In the future, this name will be used by default unless reset with --vpn=\"name\".".format(vpn_name))
    elif keyring.get_password(vpn_name, "vpn_name") != None:
        vpn_name = keyring.get_password(vpn_name, "vpn_name")
        print("Using previous VPN name of {}.  To use a different VPN name, run with --vpn=\"name\".".format(vpn_name))
    else:
        vpn_name = input("No VPN name was given. Please supply the vpn name:")  
        print("VPN name set to {}. In the future, this name will be used by default unless reset with --vpn=\"name\".".format(vpn_name))
    keyring.set_password(vpn_name, "vpn_name", vpn_name)


    
def setupCommandlineInputs():
    global args
    
    parser = argparse.ArgumentParser()
    parser.add_argument("--duration", "-d", default=defaults['duration'], help="(time in hours|'wd'|'fd') E.g., 8h, the amount of time (in hours) to keep the VPN active. Use 'wd' to do 9-12 and 1-6 (default), or 'fd' to do 9-6.")
    parser.add_argument("--clickspeed", "-cs", default=defaults['clickspeed'], help="(superfast|fast|normal|slow|superslow) adjust based on responsiveness of your GUI")
    parser.add_argument("--fillpassword", "-fp", default=defaults['fillpassword'],  help="(yes|no|andReturn) type in password and optionally hit return in the dialogs.  CAUTION: since this password is provided to the GUI, it is possible that intermediate clicks will result in your password being typed to, e.g., chat dialogs. Prevent this by using 'yes' instead of 'andReturn', or making sure the clickspeed matches your GUI responsiveness.")
#    parser.add_argument("--updatepass", "-up", default=defaults['updatepass'], help="(chrome|firefox|anyothername) opens password portal in browser.")
#    parser.add_argument("--loginonly", "-l", action="store_true", help="Logs in once and quits.")
#    parser.add_argument("--warning", "-w", default=defaults['warning'], help="(yes|no) Displays warning message prior to filling in password.")
    parser.add_argument("--simulate", "-s", action="store_true", help="When set, script which would be executed is instead printed to the terminal.")
    parser.add_argument("--reset", action="store_true", help="Use to reset your login information.")
    parser.add_argument("--vpn", "-n", help="Name of VPN to connect to. Must match your configured connection.")
    args = parser.parse_args()

def setupDelayArgs():
    global majorDelay
    global minorDelay
    
    minorDelay = clickspeed[args.clickspeed]
    majorDelay = minorDelay*2

def setupFillPasswordArgs():
    global inputPassword
    global closeDialog
    
    """Sets up applescript pieces for filling in the password.  Must setup delay first."""

    #Default: fill password, don't do anything else
    inputPassword = """
		delay {majorDelay}
		keystroke passwd
    """.format(majorDelay=majorDelay)
    closeDialog = ""
    
    if(args.fillpassword == 'yes'):
        pass
    elif(args.fillpassword == 'no'):
        inputPassword = ""
    elif(args.fillpassword == 'andReturn'):
        closeDialog =  """
		keystroke return
		delay {minorDelay}
		keystroke return

    """.format(minorDelay=minorDelay)        
    else:
        print("Invalid argument passed to --fillpassword / -fp")
        sys.exit(2)

def setupWarningArgs():
    if(args.warning == 'yes'):
        pass
      #  args.fillpassword = 'no'
    elif(args.warning == 'no'):
        pass
    elif(args.warning == 'warnOnly'):
        ## NEED TO IMPLEMENT
        pass
    else:
        print("Invalid argument passed to --warning / -w")
        sys.exit(2)

def warn():
    global alert_applescript    
    alert_applescript = """
    display dialog "VPN has disconnected" ¬
    with title "{vpn_name} no longer active" ¬
    with icon caution ¬
    buttons {{"OK"}}
    """.format(vpn_name=vpn_name)
    
    process = subprocess.Popen(["osascript", "-e","'{}'".format(alert_applescript)], stdout=subprocess.PIPE)
    out, err = process.communicate() #blocks until the process terminates
    return out

#def checkVpnStatus():
#    pass
        
def genAppleScript():
    """Outputs applescript to be run by program."""
    
    setupDelayArgs()
    setupFillPasswordArgs()
    setupWarningArgs()
    
    return """set vpn_name to "\\\"{vpn_name}\\\""
set user_name to "{username}"
set passwd to "{password}"

tell application "System Events"
	set rc to do shell script "scutil --nc status " & vpn_name
	if rc starts with "Disconnected" then
		do shell script "scutil --nc start " & vpn_name & " --user " & user_name
    {inputPassword}
    {closeDialog}
	end if
end tell
""".format(vpn_name=vpn_name,username=username,password=password,inputPassword=inputPassword, closeDialog=closeDialog)

def runScript():
    if(args.simulate == True):
        print(genAppleScript())
        return
    elif(args.warning == 'warnOnly'):
        return
    elif(args.warning == 'yes'):
        pass
    subprocess.call("""osascript -e '{}' """.format( genAppleScript() ), shell=True)
    
        
def main():
    global vpn_name

    setupCommandlineInputs()
    setVpnName()
    try:
        fetchCredentials()
    except:    
        resetCredentials()        
    
    if args.duration == 'fd':
        while(datetime.datetime.now() < dayEnds):
            runScript()
            time.sleep(int(update_interval))
        print("Completed work day. Good bye!")    
        sys.exit(0)
        
    if args.duration == 'wd':
        while(datetime.datetime.now() < dayEnds):
            if ( not( lunchBegins < datetime.datetime.now() < lunchEnds) ):
                runScript()
                time.sleep(int(update_interval))
        print("Completed work day. Good bye!")    
        sys.exit(0)
        
    else:        
        try:
            startTime = time.time()
            hours = float(str(args.duration).split("h")[0])
            secondsToRun = hours*60
        except:
            print("Invalid option passed to --duration / -d")
            sys.exit(2)

        while( (time.time() - startTime) < secondsToRun):
            runScript()
            time.sleep(int(update_interval))

        print("Completed {} hour interval. Good bye!".format(hours))    
        sys.exit(0)

if __name__ == "__main__":
    main()


