# @package      hubzero-submit-server
# @file         DaemonsInfo.py
# @copyright    Copyright (c) 2014-2020 The Regents of the University of California.
# @license      http://opensource.org/licenses/MIT MIT
#
# Copyright (c) 2012-2020 The Regents of the University of California.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# HUBzero is a registered trademark of The Regents of the University of California.
#
import os
import re
import socket
import json
import logging

from hubzero.submit.LogMessage import getLogJobIdMessage as getLogMessage

class DaemonsInfo:
   def __init__(self,
                configFilePath):
      self.logger = logging.getLogger(__name__)
      self.daemons = {}

      daemonPattern   = re.compile(r'(\s*\[)([^\s]*)(]\s*)')
      keyValuePattern = re.compile(r'( *)(\w*)( *= *)(.*[^\s$])( *)')
      commentPattern  = re.compile(r'\s*#.*')
      daemonName      = ""

      if os.path.exists(configFilePath):
         try:
            fpInfo = open(configFilePath,'r')
            try:
               eof = False
               while not eof:
                  record = fpInfo.readline()
                  if record != "":
                     record = commentPattern.sub("",record)
                     if   daemonPattern.match(record):
                        daemonName = daemonPattern.match(record).group(2)
                        self.daemons[daemonName] = {'hostname':socket.gethostname(),
                                                    'port':0,
                                                    'submitSSLcert':"/etc/submit/submit_server.crt",
                                                    'submitSSLkey':"/etc/submit/submit_server.key",
                                                    'submitSSLCA':"/etc/submit/submit_server_ca.crt"
                                                   }
                     elif keyValuePattern.match(record):
                        key,value = keyValuePattern.match(record).group(2,4)
                        if key in self.daemons[daemonName]:
                           if   isinstance(self.daemons[daemonName][key],list):
                              self.daemons[daemonName][key] = [e.strip() for e in value.split(',')]
                           elif isinstance(self.daemons[daemonName][key],bool):
                              self.daemons[daemonName][key] = bool(value.lower() == 'true')
                           elif isinstance(self.daemons[daemonName][key],float):
                              self.daemons[daemonName][key] = float(value)
                           elif isinstance(self.daemons[daemonName][key],int):
                              self.daemons[daemonName][key] = int(value)
                           elif isinstance(self.daemons[daemonName][key],dict):
                              try:
                                 sampleKey   = list(self.daemons[daemonName][key].keys())[0]
                                 sampleValue = self.daemons[daemonName][key][sampleKey]
                              except:
                                 try:
                                    self.daemons[daemonName][key] = json.loads(value)
                                 except:
                                    self.daemons[daemonName][key] = {}
                                    sampleKey   = "key"
                                    sampleValue = "value"
                              else:
                                 self.daemons[daemonName][key] = {}
               
                              if not self.daemons[daemonName][key]:
                                 for e in value.split(','):
                                    dictKey,dictValue = e.split(':')
                                    if isinstance(sampleKey,int):
                                       dictKey = int(dictKey)
                                    if   isinstance(sampleValue,int):
                                       dictValue = int(dictValue)
                                    elif isinstance(sampleValue,float):
                                       dictValue = float(dictValue)
                                    elif isinstance(sampleValue,bool):
                                       dictValue = bool(dictValue.lower() == 'true')
                                    self.daemons[daemonName][key][dictKey] = dictValue
                           else:
                              self.daemons[daemonName][key] = value
                        else:
                           message = "Undefined key = value pair %s = %s for daemon %s" % (key,value,daemonName)
                           self.logger.log(logging.WARNING,getLogMessage(message))
                  else:
                     eof = True
            except (IOError,OSError):
               self.logger.log(logging.ERROR,getLogMessage("Daemons configuration file %s could not be read" % (configFilePath)))
            finally:
               fpInfo.close()
         except (IOError,OSError):
            self.logger.log(logging.ERROR,getLogMessage("Daemons configuration file %s could not be opened" % (configFilePath)))
      else:
         self.logger.log(logging.ERROR,getLogMessage("Daemons configuration file %s is missing" % (configFilePath)))


   def getDaemonListenURI(self,
                          daemonName,
                          protocol='tls'):
      listenURI = ""
      if daemonName in self.daemons:
         hostName = socket.gethostname()
         daemon = self.daemons[daemonName]
         if daemon['hostname'] == hostName:
            daemonHost = ""
         else:
            daemonHost = daemon['hostname']

         if protocol in ['tls','tcp']:
            listenURI = "%s://%s:%d" % (protocol,daemonHost,daemon['port'])
         else:
            self.logger.log(logging.ERROR,getLogMessage("Invalid protocol %s" % (protocol)))

      return(listenURI)


