""" The Machine/Job Features TimeLeft utility interrogates the MJF values
    for the current CPU and Wallclock consumed, as well as their limits.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

__RCSID__ = "$Id$"

import os
import time
from six.moves.urllib.request import urlopen

from DIRAC import S_OK, S_ERROR
from DIRAC.Resources.Computing.BatchSystems.TimeLeft.ResourceUsage import ResourceUsage


class MJFResourceUsage(ResourceUsage):
  """
   This is the MJF plugin of the TimeLeft Utility
  """

  #############################################################################
  def __init__(self):
    """ Standard constructor
    """
    super(MJFResourceUsage, self).__init__('MJF', 'JOB_ID')

    self.queue = os.environ.get('QUEUE')

    self.log.verbose('jobID=%s, queue=%s' % (self.jobID, self.queue))
    self.startTime = time.time()

  #############################################################################
  def getResourceUsage(self):
    """ Returns S_OK with a dictionary containing the entries CPU, CPULimit,
        WallClock, WallClockLimit, and Unit for current slot.
    """

    cpuLimit = None
    wallClockLimit = None
    wallClock = None
    jobStartSecs = None

    jobFeaturesPath = None
    machineFeaturesPath = None

    # Getting info from JOBFEATURES
    try:
      # We are not called from TimeLeft.py if these are not set
      jobFeaturesPath = os.environ['JOBFEATURES']
    except KeyError:
      self.log.warn('$JOBFEATURES is not set')

    if jobFeaturesPath:
      try:
        wallClockLimit = int(urlopen(jobFeaturesPath + '/wall_limit_secs').read())
        self.log.verbose("wallClockLimit from JF = %d" % wallClockLimit)
      except ValueError:
        self.log.warn("/wall_limit_secs is unreadable")
      except IOError as e:
        self.log.exception("Issue with $JOBFEATURES/wall_limit_secs", lException=e)
        self.log.warn("Could not determine cpu limit from $JOBFEATURES/wall_limit_secs")

      try:
        jobStartSecs = int(urlopen(jobFeaturesPath + '/jobstart_secs').read())
        self.log.verbose("jobStartSecs from JF = %d" % jobStartSecs)
      except ValueError:
        self.log.warn("/jobstart_secs is unreadable, setting a default")
        jobStartSecs = self.startTime
      except IOError as e:
        self.log.exception("Issue with $JOBFEATURES/jobstart_secs", lException=e)
        self.log.warn("Can't open jobstart_secs, setting a default")
        jobStartSecs = self.startTime

      try:
        cpuLimit = int(urlopen(jobFeaturesPath + '/cpu_limit_secs').read())
        self.log.verbose("cpuLimit from JF = %d" % cpuLimit)
      except ValueError:
        self.log.warn("/cpu_limit_secs is unreadable")
      except IOError as e:
        self.log.exception("Issue with $JOBFEATURES/cpu_limit_secs", lException=e)
        self.log.warn('Could not determine cpu limit from $JOBFEATURES/cpu_limit_secs')

      wallClock = int(time.time()) - jobStartSecs

    # Getting info from MACHINEFEATURES
    try:
      # We are not called from TimeLeft.py if these are not set
      machineFeaturesPath = os.environ['MACHINEFEATURES']
    except KeyError:
      self.log.warn('$MACHINEFEATURES is not set')

    if machineFeaturesPath and jobStartSecs:
      try:
        shutdownTime = int(urlopen(machineFeaturesPath + '/shutdowntime').read())
        self.log.verbose("shutdownTime from MF = %d" % shutdownTime)
        if int(time.time()) + wallClockLimit > shutdownTime:
          # reduce wallClockLimit if would overrun shutdownTime
          wallClockLimit = shutdownTime - jobStartSecs
      except ValueError:
        self.log.warn("/shutdowntime is unreadable")
      except IOError as e:
        self.log.warn("Issue with $MACHINEFEATURES/shutdowntime", repr(e))
        self.log.warn('Could not determine a shutdowntime value from $MACHINEFEATURES/shutdowntime')

    # Reporting
    consumed = {'CPU': None, 'CPULimit': cpuLimit, 'WallClock': wallClock, 'WallClockLimit': wallClockLimit}
    if cpuLimit and wallClock and wallClockLimit:
      self.log.verbose("MJF consumed: %s" % str(consumed))
      return S_OK(consumed)
    self.log.info('Could not determine some parameters')
    retVal = S_ERROR('Could not determine some parameters')
    retVal['Value'] = consumed
    return retVal
