#!/usr/bin/python2
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2014 University of Arizona
# Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
# See COPYING for copyright and distribution information.
#

import time
import errno
import subprocess
import multiprocessing as mp

class ProcessManager:

    manager = mp.Manager()
    processes = dict()
    subprocesses = manager.dict()
    results = manager.dict()

    def cleanupProcesses(self):
        self.processes.clear()
        self.subprocesses.clear()
        self.results.clear()

    def runProcess(self, processKey, processCallFormat, message, subprocesses, results):
        print message
        process = subprocess.Popen(
            processCallFormat, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
        subprocesses[processKey] = process
        try:
            stdout, stderr = process.communicate()
            returnCode = process.returncode
            results[processKey] = (returnCode, stdout, stderr)
        except IOError as e:
            pass

    def startProcess(self, processKey, processCallFormat, message):
        self.processes[processKey] = mp.Process(
            target = self.runProcess,
                args = [processKey, processCallFormat, message, self.subprocesses, self.results])
        self.processes[processKey].start()

    def killProcess(self, processKey):
        if processKey not in self.results:
            self.subprocesses[processKey].terminate()

    def hasProcessCompleted(self, processKey):
        if processKey in self.results:
            return True
        else:
            return False

    def waitForProcessCompletion(self, processKey, waitTime):
        self.processes[processKey].join(waitTime)

    def getProcessReturnCode(self, processKey):
        if processKey in self.results:
            (returnCode, stdout, stderr) = self.results[processKey]
            return returnCode
        else:
            print "Invalid processKey provided - " + processKey
            return -1

    def getProcessError(self, processKey):
        if processKey in self.results:
            (returnCode, stdout, stderr) = self.results[processKey]
            return stderr
        else:
            return "Error not available for processKey - " + processKey

    def getProcessOutput(self, processKey):
        if processKey in self.results:
            (returnCode, stdout, stderr) = self.results[processKey]
            return stdout
        else:
            return "Output not available for processKey - " + processKey

    def startNfd(self):
        self.startProcess("nfd", ["sudo", "nfd"], "-> Starting NFD")

    def killNfd(self):
        self.killProcess("nfd")
        time.sleep(2)
