#!/usr/bin/env python3
# Copyright (c) 2007 Arista Networks, Inc.  All rights reserved.
# Arista Networks, Inc. Confidential and Proprietary.

# pylint: disable=consider-using-f-string

import optparse # pylint: disable=deprecated-module
parser = optparse.OptionParser()
parser.usage = "%prog [ OPTIONS ]"
parser.add_option( "-s", "--sysname", action="store",
                   help="System name (default: %default)",
                   default="ar" )
parser.add_option( "-o", action="store", type="str", default="/var/log/temperature",
                   help="log file (default: %default)" )
parser.add_option( "-i", action="store", type="int", default=5*60,
                   help="interval in seconds (default: %default )" )
( options, args ) = parser.parse_args()
if args: 
   parser.error( "Unexpected arguments:" + " ".join(args) )
logfile = options.o

failed = False
def log(logmsg):
   global failed
   stime = time.strftime( "%X %x %Z" )
   try:
      # pylint: disable-next=consider-using-with
      open( logfile, "a" ).write( stime + ": " + logmsg + "\n" )
      failed = False
   except OSError:
      if not failed:
         print( "%s: failed to write log file '%s'" % ( stime, logfile ) )
         failed = True
   print( "%s: %s" % ( stime, logmsg ) )

tempAlarmLevelToStr = { 'unknownTemperatureAlarmLevel' : 'Unknown',
                        'temperatureOk' : 'Ok',
                        'temperatureOverheating' : 'Overheating',
                        'temperatureSensorFailure' : 'Sensor Failed',
                        'temperatureCritical' : 'Critical' }

import EntityManager, time, EntityMib, sys # pylint: disable=wrong-import-position
em = EntityManager.Sysdb( sysname = options.sysname )
mg = em.mountGroup()
tempStatus = mg.mount( "environment/archer/temperature/status",
                       "Environment::Temperature::Status", "ri" )
tempConfig = mg.mount( "environment/temperature/config",
                       "Environment::Temperature::Config", "r" )
ts = mg.mount( "environment/thermostat/status",
               "Environment::Thermostat::Status", "r" )

entmib = mg.mount( "hardware/entmib", "EntityMib::Status", "r" )
mg.close( blocking=True )
root = em.root()

def _indentStr( indentLevel ):
   return '   ' * indentLevel

def _printModuleTempSensorInfo( tempSensors, indentLevel=0 ):
   tempSensors.sort( key=lambda ts: ts.label )
   for tempSensor in tempSensors:
      name = EntityMib.componentName( tempSensor )
      tsc = tempConfig.tempSensor.get( name )
      tss = tempStatus.get( name )
      if not tsc or not tss:
         # sensor has been removed
         continue
      prefix = "%sSensor %s" % ( _indentStr( indentLevel ), 
                                 tempSensor.label )
      log( "%s description: %s" %( prefix, tsc.description ) )
      if tss.hwStatus == "ok":
         log( "%s temperature: %0.2fC" %( prefix, tss.temperature ) )
      elif tss.hwStatus == "unknownHwStatus":
         log( "%s temperature: Unknown" %( prefix ) )
      else:
         log( "%s temperature: Sensor Failed" %( prefix ) )
         
def dumpTemperature():
   entityMibRoot = root[ 'hardware' ][ 'entmib' ].root
   thermostatStatus = root[ 'environment' ][ 'thermostat' ][ 'status' ]

   log( "System temperature status is: %s" \
         % tempAlarmLevelToStr[ thermostatStatus.temperatureAlarmLevel ] )

   if entityMibRoot is None or entityMibRoot.initStatus != "ok":
      # Hardware not discovered yet
      return
   elif entityMibRoot.tacType.fullTypeName == "EntityMib::Chassis":
      for slot in entityMibRoot.cardSlot.values():
         if slot.card is not None:
            # Card is inserted
            log( "%s %s:" %( slot.tag, slot.label ) )
            tempSensors = [ sensor for sensor in slot.card.sensor.values()
                            if sensor.tag == "TempSensor" ]
            _printModuleTempSensorInfo( tempSensors, indentLevel=1 )
   elif entityMibRoot.tacType.fullTypeName == "EntityMib::FixedSystem":
      tempSensors = [ sensor for sensor in entityMibRoot.sensor.values()
                      if sensor.tag == "TempSensor" ]
      _printModuleTempSensorInfo( tempSensors, indentLevel=0 )

import Tac # pylint: disable=wrong-import-position
while True:
   dumpTemperature()
   sys.stdout.flush()
   Tac.runActivities( options.i )
