#########################################################################
#
#   Copyright 2021 VMware, Inc.  All rights reserved. VMware Confidential
#
#########################################################################
from logging import getLogger

from os.path import join
from cis.utils import read_properties, write_props_to_file, \
text_subst_in_file
from .patchUtil import TO_PREPARE_SUFFIX, updateVersion

VERSION = 5
EAM_CFG_DIR = "/etc/vmware-eam/"
EAM_VERSION = "version"
LOG4J_PROPS_FILE_OLD = join(EAM_CFG_DIR, "log4j.properties")
LOG4J_PROPS_FILE_NEW = LOG4J_PROPS_FILE_OLD + TO_PREPARE_SUFFIX
EAM_VERSION_OLD = join(EAM_CFG_DIR, EAM_VERSION)
EAM_VERSION_NEW = join(EAM_CFG_DIR, EAM_VERSION + TO_PREPARE_SUFFIX)

_log = getLogger(__name__)

_EAM_ROOT_LEVEL_PATTERN = "${eam.rootLogLevel}"
_VIM_LOG_DIR_PATTERN = "${vim.logdir}"

_CONFIG_TO_ADD = {
   "appender.api_appender.type" : "RollingFile",
   "appender.api_appender.name" : "apiAppender",
   "appender.api_appender.fileName" : _VIM_LOG_DIR_PATTERN + "/eam_api.log",
   "appender.api_appender.filePattern" : _VIM_LOG_DIR_PATTERN + "/eam_api-%i.log.gz",
   "appender.api_appender.layout.type" : "PatternLayout",
   "appender.api_appender.layout.pattern" : "%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} | %5p | %t | %F | %L | %m%n",
   "appender.api_appender.policies.type" : "Policies",
   "appender.api_appender.policies.size.type" : "SizeBasedTriggeringPolicy",
   "appender.api_appender.policies.size.size" : "50MB",
   "appender.api_appender.strategy.type" : "DefaultRolloverStrategy",
   "appender.api_appender.strategy.max" : "20",
   "appender.api_appender.strategy.fileIndex" : "min",

   "logger.api_client_authenticator.appenderRef.rolling.ref " : "apiAppender",
   "logger.api_client_authenticator.additivity" : "false",
   "logger.api_client_authenticator.name" : "com.vmware.eam.security.ClientAuthenticator",
   "logger.api_client_authenticator.level" : _EAM_ROOT_LEVEL_PATTERN,

   "logger.api_localization.appenderRef.rolling.ref " : "apiAppender",
   "logger.api_localization.additivity" : "false",
   "logger.api_localization.name" : "com.vmware.eam.util.LocalizationFilter",
   "logger.api_localization.level" : _EAM_ROOT_LEVEL_PATTERN,

   "logger.api_session_manager.appenderRef.rolling.ref" : "apiAppender",
   "logger.api_session_manager.additivity" : "false",
   "logger.api_session_manager.name" : "com.vmware.eam.vim.security.impl.SessionManager",
   "logger.api_session_manager.level" : _EAM_ROOT_LEVEL_PATTERN
}

_ROLLING_APPENDER = "appender.rolling"
_ROLLING_APPENDER_NAME_KEY = _ROLLING_APPENDER + ".name"
_SERVICE_APPENDER_NAME = "coreServiceAppender"
_ROOT_LOGGER_REF_KEY = "rootLogger.appenderRef.rolling.ref"
_CORE_APPENDER_PROP = "appender.core_service_appender"
_CORE_APPENDER_FILE_NAME = _CORE_APPENDER_PROP + ".fileName"
_EAM_LOG_LEVEL_PROP = "logger.eam.level"

def run(ctx, isExpand):
   """
   Configures log4j to log eam logs in two separate files (core and api)
   updating the log4j.properties file.

   :param: ctx : B2B context
   :type: ctx : PatchContext, B2B specific structure, please refer to B2B
               documentation.
   :param: isExpand: boolean flag, True if this patch is invoked from expand
                    phase, False otherwise.
   :type: bool
   """

   file = LOG4J_PROPS_FILE_NEW if isExpand else LOG4J_PROPS_FILE_OLD
   versionFile = EAM_VERSION_NEW if isExpand else EAM_VERSION_OLD

   _log.info(
       "Configuring log4j to log eam logs in two separate files by updating {}"
       .format(file)
   )

   try:
      oldProps = read_properties(file)
      newProps = dict()

      for key, value in  oldProps.items():
         if key.startswith(_ROLLING_APPENDER):
            if key == _ROLLING_APPENDER_NAME_KEY:
               value = _SERVICE_APPENDER_NAME
            key = key.replace(_ROLLING_APPENDER, _CORE_APPENDER_PROP, 1)
         elif key == _ROOT_LOGGER_REF_KEY:
            value = _SERVICE_APPENDER_NAME

         newProps[key] = value

      for key, value in _CONFIG_TO_ADD.items():
         newProps[key] = value

      write_props_to_file(file, newProps.items())

      _replacePlaceholders(file, newProps)

      _log.info("Configuration completed")
      updateVersion(VERSION, versionFile)
   except Exception as e:
      _log.error("EAM version five patch failed.", exc_info=True)
      raise e


def updateReplicationConfig(replicationConfig):
   """
    Updates given replication config with patch specific config
   file replication configuration.

   Each item in the dictionary have following semantic:
      Key -> path of a file from source machine
      Value -> path of a file from target machine
   The file from source machine is replicated on the location pointed
   in the value over the target machine. If the Value is None, the file
   is not replicated.

   :param: replicationConfig: dictionary where to place patch specific
           config replication.
   :type: dict(str, str)
   """
   replicationConfig[EAM_VERSION_OLD] = None
   replicationConfig[EAM_VERSION_NEW] = EAM_VERSION_OLD
   replicationConfig[LOG4J_PROPS_FILE_OLD] = None
   replicationConfig[LOG4J_PROPS_FILE_NEW] = LOG4J_PROPS_FILE_OLD

def _replacePlaceholders(file, newProps):
   eamLogLevel = newProps[_EAM_LOG_LEVEL_PROP]
   coreLogFile = newProps[_CORE_APPENDER_FILE_NAME]

   _log.info("Core log file {}".format(coreLogFile))
   logDir = coreLogFile[0:coreLogFile.rfind("/")]
   text_subst_in_file(file, {
      _EAM_ROOT_LEVEL_PATTERN : eamLogLevel,
      _VIM_LOG_DIR_PATTERN: logDir})
