#!/usr/bin/env python

import sys
import os
import re
import json
import argparse
import platform
import fnmatch
sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
import featureState
from subprocess import check_output
from tempfile import mkstemp
from shutil import move

VCHAEnabled = False
featureState.init(False)
if featureState.getVCHA():
   VCHAEnabled = True

WINDOWS = False
if 'Windows' in platform.platform():
   WINDOWS = True
   import win32file

if WINDOWS:
   DEBUG_FILE_DIR = os.path.join(os.environ['VMWARE_CFG_DIR'], 'vmware-vpx')
   LOG_DIR = os.path.join(os.environ['VMWARE_LOG_DIR'], 'vmware-vpx')
   REL_DIR = os.path.join(os.environ['VMWARE_CIS_HOME'], 'vpxd')
else:
   DEBUG_FILE_DIR = '/etc/vmware-vpx'
   LOG_DIR = os.path.join(os.environ['VMWARE_LOG_DIR'], 'vmware', 'vpxd')
   REL_DIR = os.path.join(os.environ['VMWARE_CIS_HOME'], 'vmware-vpx')

LOG_FILE = 'vpxd.log'
DEBUG_FILE = 'vpxdDebug'
DEBUG_DIR = os.path.join(REL_DIR, 'debug')


def modifySCVpxdConfig(exeFilePath):
   binPath = 'binPath=\"%s\"' % exeFilePath
   check_output(["cmd" "/c" "sc", "config", "vpxd", binPath], shell=True)


def modifyVMonVpxdConfig(debug):
   vpxdVMonCfgFile = os.path.join(os.environ['VMWARE_CFG_DIR'], 'vmware-vmon',
                                  'svcCfgfiles', 'vpxd.json')
   exeFilePath = "%VMWARE_CIS_HOME%/vpxd/"
   if debug:
      exeFilePath += "debug/vpxd.exe"
   else:
      exeFilePath += "vpxd.exe"

   with open(vpxdVMonCfgFile, 'r') as vpxdJson:
      vpxdCfg = json.load(vpxdJson)
      vpxdCfg["StartCommand"] = exeFilePath

   # Write to temp file and then replace vpxd.json with temp file
   fd, tempFile = mkstemp()
   with open(tempFile, mode="w") as newVpxdJson:
      newVpxdJson.write(json.dumps(vpxdCfg, indent=3, sort_keys=True))
   os.close(fd)
   move(tempFile, vpxdVMonCfgFile)


def enableVpxdDebug():
   """
   Create a file that indicates vpxd should be run in debug mode. Also, create
   symlinks from release bits dir to debug bits dir for all files that are
   missing in debug dir (except for debug dir itself).

   For Windows, create a Junction for a directory instead of symlink and modify
   SCM entry for vpxd so that it points to debug binary.
   """
   try:
      debugFilepath = os.path.join(DEBUG_FILE_DIR, DEBUG_FILE)
      with open(debugFilepath, mode='a'):
         pass

      relFileList = os.listdir(REL_DIR)
      for item in relFileList:
         srcFilePath = os.path.join(REL_DIR, item)
         dstFilepath = os.path.join(DEBUG_DIR, item)
         if not (os.path.isfile(dstFilepath) or os.path.isdir(dstFilepath)) and not os.path.islink(dstFilepath):
            if not fnmatch.fnmatch(item, 'debug'):
               if WINDOWS:
                  if os.path.isdir(srcFilePath):
                     check_output(["cmd", "/c", "mklink", "/J", dstFilepath,
                                  srcFilePath], shell=True)
                  else:
                     win32file.CreateSymbolicLink(dstFilepath, srcFilePath, 0)
               else:
                  os.symlink(srcFilePath, dstFilepath)
      if WINDOWS:
         debugVpxdExe = os.path.join(DEBUG_DIR, 'vpxd.exe')
         if VCHAEnabled:
            modifyVMonVpxdConfig(debug=True)
         else:
            modifySCVpxdConfig(debugVpxdExe)

      print("Setup complete, restart vpxd to run in debug mode")
   except Exception as exc:
      print("Error while enabling debug mode for vpxd: %s" % str(exc))


def disableVpxdDebug():
   """
   Delete the file that indicates vpxd will run in debug mode when restarted.

   For Windows, modify SCM entry for vpxd so that it points to non-debug binary.
   """
   debugFilepath = os.path.join(DEBUG_FILE_DIR, DEBUG_FILE)
   try:
      os.remove(debugFilepath)
   except IOError as exc:
      print("Error while deleting file: %s\n%s" % (debugFilepath, str(exc)))
   try:
      if WINDOWS:
         relVpxdExe = os.path.join(REL_DIR, 'vpxd.exe')
         if VCHAEnabled:
            modifyVMonVpxdConfig(debug=False)
         else:
            modifySCVpxdConfig(relVpxdExe)
   except Exception as exc:
      print("Error while disabling debug mode for vpxd: %s" % str(exc))
   print("Setup complete, restart vpxd to run in regular (non-debug) mode")


if __name__ == '__main__':
   parser = argparse.ArgumentParser()
   group = parser.add_mutually_exclusive_group()
   group.add_argument("-e", "--enable", dest="enable", default=False,
                       action="store_true",
                       help="Run vpxd in debug mode after it restarts")
   group.add_argument("-d", "--disable", dest="disable", default=False,
                       action="store_true",
                       help="Run vpxd in regular mode after it restarts")
   options = parser.parse_args()

   if (options.enable):
      enableVpxdDebug()

   if (options.disable):
      disableVpxdDebug()
