import subprocess
from Logger import Logger
#from ToolChainUtils import ToolChainUtils
from CommandUtils import CommandUtils
import os
import threading
import time
from time import sleep
from constants import constants

chrootRootPath="/mnt"

class ChrootUtils(object):
    counter=1
    lockForCounter=threading.Lock()
    lockForTrackingChroots=threading.Lock()
    lockForCreateChroot=threading.Lock()
    activeChroots=[]
    failureFlag=False
    
    def __init__(self,logName=None,logPath=None):
        if logName is None:
            logName = "ChrootUtils"
        if logPath is None:
            logPath = constants.logPath
        self.logName=logName
        self.logPath=logPath
        self.logger=Logger.getLogger(logName,logPath)
        
    def _getChrootUniqueID(self):
        ChrootUtils.lockForCounter.acquire()
        chrootID=chrootRootPath+"/photonroot"+str(ChrootUtils.counter)
        while os.path.isdir(chrootID):
            ChrootUtils.counter = ChrootUtils.counter +1
            chrootID=chrootRootPath+"/photonroot"+str(ChrootUtils.counter)
        ChrootUtils.counter = ChrootUtils.counter +1
        ChrootUtils.lockForCounter.release()
        return chrootID
    
    def checkFreeSpace(self):
        process = subprocess.Popen(["df" ,chrootRootPath],shell=True,stdout=subprocess.PIPE)
        retval = process.wait()
        if retval != 0:
            self.logger.error("Unable to check free space. Unknown error.")
            return False
        output = process.communicate()[0]
        device, size, used, available, percent, mountpoint = output.split("\n")[1].split()
        if available > 600000:
            self.logger.info("Free Space available "+ available)
            return True
        return False
    
    def createChroot(self):
        if ChrootUtils.failureFlag:
            return False
        
        ChrootUtils.lockForCreateChroot.acquire()
        if ChrootUtils.failureFlag:
            ChrootUtils.lockForCreateChroot.release()
            return False
        
        startTime=currentTime=time.time()
        timeOut=1800
        freeSpaceAvailable=False
        while currentTime < startTime + timeOut:
            #if self.checkFreeSpace():
            if len(ChrootUtils.activeChroots) < 2:
                freeSpaceAvailable=True
                break
            sleep(100)
            
        if not freeSpaceAvailable:
            self.logger.error("Unable to create chroot. No sufficient free space is available.")
            ChrootUtils.lockForCreateChroot.release()
            ChrootUtils.failureFlag=True
            return False,None
        
        chrootID=self._getChrootUniqueID()
        # need to add timeout for this step
        # http://stackoverflow.com/questions/1191374/subprocess-with-timeout
        process = subprocess.Popen("mkdir -p "+chrootID,shell=True,stdout=subprocess.PIPE)
        retval = process.wait()
        
        ChrootUtils.lockForCreateChroot.release()
        
        if retval != 0:
            self.logger.error("Unable to create chroot:"+ chrootID +".Unknown error.")
            return False,None
        
        ChrootUtils.lockForTrackingChroots.acquire()
        ChrootUtils.activeChroots.append(chrootID) 
        ChrootUtils.lockForTrackingChroots.release()           
        return True,chrootID
    
    def destroyChroot(self,chrootID):
        validChroot = True
        ChrootUtils.lockForTrackingChroots.acquire()
        if chrootID not in ChrootUtils.activeChroots:
            validChroot = False
        else:
            ChrootUtils.activeChroots.remove(chrootID)
        ChrootUtils.lockForTrackingChroots.release()
        if not validChroot:
            self.logger.error("Given chroot:"+chrootID+" is not a valid chroot. It is not created by ChrootUtils.")
            return False

        # need to add timeout for this step
        # http://stackoverflow.com/questions/1191374/subprocess-with-timeout
        process = subprocess.Popen("./cleanup-build-root.sh "+chrootID,shell=True,stdout=subprocess.PIPE)
        retval = process.wait()
        if retval != 0:
            self.logger.error("Unable to destroy chroot:"+ chrootID +".Unknown error.")
            return False
        cmdUtils=CommandUtils()
        cmdUtils.run_command("rm -rf "+chrootID)
        ChrootUtils.lockForTrackingChroots.acquire()
        ChrootUtils.lockForTrackingChroots.release()
        self.logger.info("Successfully destroyed chroot:"+chrootID)
        return True