#!/usr/bin/env python

from __future__ import print_function

import re
import sys
import os
import platform
import time
from subprocess import *

case_sensitive = False
P4BIN = os.getenv ('P4BIN', 'p4')

if platform.system() == "Windows":
  p4 = "p4.exe"
else:
  p4 = P4BIN


def loadconfig():
  global case_sensitive

  robots = set()
  servers = []

  cfgfile = open("totalusers.cfg", "r")

  for line in cfgfile.readlines():
    if (re.search("^#", line) or re.search("^\s*$", line)):
      continue

    if re.search("^case_sensitive", line):
      if re.match("^case_sensitive=1.*", line):
        case_sensitive = True
        log("DEBUG", "Operating in case sensitive mode.")
      else:
        log("DEBUG", "Operating in case insensitive mode.")

    if re.search("^ROBOT", line):
      robotuser = (re.match("^ROBOT\|(.*)", line).groups()[0])
      if case_sensitive:
        log("DEBUG", "Robot user %s added." % (robotuser))
        robots.add(robotuser)
      else:
        log("DEBUG", "Robot user %s added." % (robotuser.lower()))
        robots.add(robotuser.lower())

    if re.search("^SERVER", line):
      server = (re.match("^SERVER\|(.*)\|(.*)\|(.*)", line).groups())
      log("DEBUG", "Server %s added." % (server[0]))
      servers.append(server)

  if servers == []:
    log("ERROR", "No servers found in config file.")

  cfgfile.close()
  return servers, robots


def log(msglevel="DEBUG", message=""):
  if msglevel == "ERROR":
    print(message)
    sys.exit(1)
  else:
    print(message)


def runp4cmd(cmd):
  try:
    pipe = Popen(p4 + cmd, shell=True, stdin=PIPE, stdout=PIPE, universal_newlines=True)
    stdout, stderr = pipe.communicate()
    log("DEBUG", stdout)
    if pipe.returncode != 0:
      log("ERROR", "%s%s generated the following error: %s" % (p4, cmd, stderr))
    else:
      return stdout
  except OSError as err:
    log("ERROR", "Execution failed: %s" % (err))


def process_servers(servers, robots):
  """
  Each server line contains four components as follows:
  SERVER|port|user
  """
  users = []
  useremail = {}
  accesstimes = {}
  userserver = {}

  for server in servers:
    args = " -p %s -u %s " % (server[0], server[1])
    runp4cmd(args + "login -a < /p4/common/config/.p4passwd.p4_%s.admin" % server[2])
    runp4cmd(args + "-Ztag -F %User%,%Email%,%Access% users > users.txt")
    userfile = open("users.txt", "r")
    for userline in userfile.readlines():
      user = re.match("(.*),(.*),(.*)", userline).groups()
      if case_sensitive:
        username = user[0]
      else:
        username = user[0].lower()
      if username not in robots:
        if username not in users:
          users.append(username)
          if (user[1] != None):
            useremail[username] = user[1]
          else:
            useremail[username] = username
          accesstimes[username] = user[2]
          userserver[username] = server[0]
        else:
          if (int(accesstimes[username]) < int(user[2])):
            accesstimes[username] = user[2]
            userserver[username] = server[0]
    userfile.close()
    os.remove("users.txt")

  count = 0
  users.sort()

  totalusersfile = "totalusers.csv"

  totalusers = open(totalusersfile, "w")

  totalusers.write("Username,Email,Unix Access Time,Server,Human Readable Time Date\n")
  for user in users:
    totalusers.write("%s,%s,%s,%s,%s\n" % (user, useremail[user], accesstimes[user], userserver[user], time.ctime(int(accesstimes[user])) ))
    count += 1

  totalusers.close()
  print("\nTotal number of users: %s" % (count))
  print("User list is in %s" % (totalusersfile))


if __name__ == "__main__":
  if len(sys.argv) > 1:
    print("This program doesn't accept any arguments. Just update the totalusers.cfg file and run the program.")
  servers, robots = loadconfig()
  process_servers(servers, robots)
  sys.exit(0)

