import os
import fnmatch
import subprocess
import tarfile
from casac import casac
import datetime
import time
import urllib2
import __casac__
import TelemetryLogMonitor
import ssl

class telemetry:

    def __init__(self, casa):

        self.setCasaVersion()
        self.setHostId()
        self.logdir = casa['dirs']['rc']
        self.variantSuffix = ""
        if len(casa['variant'])>1:
            self.variantSuffix = "-" + casa['variant']
        self.logpattern = 'casastats-' + self.casaver + '-' + self.hostid + '*' + self.variantSuffix + '.log'
        self.sendlogpattern = 'casastats-*'+ self.hostid + '*.log'
        self.stampfile = self.logdir + '/telemetry-' + self.hostid + '.stamp'
        self.casa = casa

        logfiles = []

        # Check if user has defined a telemetry log location
        casa_util = __casac__.utils.utils()

        if (casa_util.getrc("TelemetryLogDirectory") != 'Unknown value'):
            self.logdir = casa_util.getrc("TelemetryLogDirectory")

        for file in os.listdir(self.logdir):
            if fnmatch.fnmatch(file, self.logpattern):
                 #print "Matched: " + file
                 logfiles.append(file)

        logfiles.sort(reverse=True)
        # Size of the existing (non-active) logfiles
        inactiveTLogSize = 0

        if (logfiles and logfiles[0] != None):
            print "Found an existing telemetry logfile: " + self.logdir  + "/" + logfiles[0]
            casa['files']['telemetry-logfile'] = self.logdir  + "/" + logfiles[0]
            for i in range(1, len(logfiles)):
                inactiveTLogSize = inactiveTLogSize + os.path.getsize(self.logdir  + "/" + logfiles[i])/1024
                #print "Inactive log size: " + str(inactiveTLogSize)
        else :
            print "Creating a new telemetry file"
            self.setNewTelemetryFile()

        # Setup Telemetry log size monitoring
        # Size limit for the telemetry logs
        tLogSizeLimit = 20000
        # File size check interval
        tLogSizeInterval = 60
        try:
            tLogSizeLimit = int(casa_util.getrc("TelemetryLogLimit"))
            tLogSizeInterval = int(casa_util.getrc("TelemetryLogSizeInterval"))
        except:
            pass
        # Subtract the inactive log sizes from the total log file size limit
        tLogSizeLimit = tLogSizeLimit - inactiveTLogSize
        if (tLogSizeLimit <= 0):
            print "Telemetry log size limit exceeded. Disabling telemetry."
            casa['state']['telemetry-enabled'] = False
        else :
            tLogMonitor = TelemetryLogMonitor.TelemetryLogMonitor()
            tLogMonitor.start(casa['files']['telemetry-logfile'],tLogSizeLimit, tLogSizeInterval, casa)
            print "Telemetry initialized. Telemetry will send anonymized usage statistics to NRAO."
            print 'You can disable telemetry by adding the following line to your ~/.casarc file:'
            print 'EnableTelemetry: False'

    def setNewTelemetryFile(self):
        self.casa['files']['telemetry-logfile'] =  self.logdir + '/casastats-' + self.casaver +'-'  + self.hostid + "-" + time.strftime("%Y%m%d-%H%M%S", time.gmtime()) + self.variantSuffix + '.log'
        # Work around the chicken/egg problem with telemetry/logger initialization
        if hasattr(self, 'logger'):
            self.logger.setstatslogfile(self.casa['files']['telemetry-logfile'])

    def setCasaVersion(self):
        myUtils = casac.utils()
        ver = myUtils.version()
        self.casaver = str(ver[0])+ str(ver[1]) + str(ver[2])+ "-" + str(ver[3])

    def setHostId(self):
        telemetryhelper = casac.telemetryhelper()
        self.hostid = telemetryhelper.getUniqueId()

    def setCasaLog(self, logger):
        self.logger = logger

    def submitStatistics(self):
        if (self.casa['state']['telemetry-enabled'] == True):
            self.logger.post("Checking telemetry submission interval")
            self.createStampFile()
            if (self.isSubmitInterval()):
                postingUrl = 'https://casa.nrao.edu/cgi-bin/crash-report.pl'
                if os.environ.has_key('CASA_CRASHREPORT_URL') :
                    postingUrl = os.environ['CASA_CRASHREPORT_URL']
                self.send(postingUrl)
                self.refreshStampFile()
                self.setNewTelemetryFile()


    def isSubmitInterval(self):
        currentTime = time.time()
        lastUpdateTime = time.time()
        if (os.path.isfile(self.stampfile)):
            lastUpdateTime = os.path.getmtime(self.stampfile)

        # Check update checkSubmitInterval
        interval = 604800
        utils = casac.utils()
        if (utils.getrc("TelemetrySubmitInterval") != 'Unknown value'):
            interval = float(utils.getrc("TelemetrySubmitInterval"))
        if ((currentTime - lastUpdateTime)> interval):
            self.logger.post("Telemetry submit interval reached, submitting telemetry data.")
            return True
        else:
            self.logger.post("Telemetry submit interval not reached. Not submitting data.")
            #print "lastUpdateTime" +str(lastUpdateTime)
            #print "currentTime" +str(currentTime)
            self.logger.post("Next telemetry data submission in: " + str(datetime.timedelta(  \
                    seconds=(interval-(currentTime-lastUpdateTime)))))
            return False

    def createStampFile(self):
        #print "Checking for stampfile " + self.stampfile
        if not os.path.isfile(self.stampfile):
            self.logger.post("Creating a new telemetry time stamp file." + self.stampfile)
            open(self.stampfile, 'a').close()

    def refreshStampFile(self):
        os.utime(self.stampfile, None)

    def send(self, telemetry_url):

        telemetryhelper = casac.telemetryhelper()
        logfiles = []

        # Test if internet connection is available.
        context = ssl._create_unverified_context()
        try:
            urllib2.urlopen('https://casa.nrao.edu/', timeout=20, context=context)
        except urllib2.URLError as err:
            self.logger.post("No telemetry server available. Not submitting data")
            return

        # Find logfiles
        for file in os.listdir(self.logdir):
            if fnmatch.fnmatch(file, self.sendlogpattern):
                #print "Matched: " + file
                logfiles.append(file)

        if (len(logfiles) > 0):
            #Tar logfiles
            current_date = datetime.datetime.today().strftime('%Y%m%d%H%M%S')
            tarfileid = self.logdir + "/telemetry-" \
                            + telemetryhelper.getUniqueId() + "-" \
                            + current_date + ".tar.gz"
            try:
                tar = tarfile.open(tarfileid, "w:gz")
                for logfile in logfiles:
                    tar.add(self.logdir + "/" + logfile,
                            arcname='telemetry/'+logfile)
                tar.close()
            except Exception as e:
                self.logger.post("Couldn't create telemetry tarfile")
                self.logger.post(str(e))

            try:
                file_param = 'file=@' + tarfileid #+ '\"'
                # Submit tarfile
                #print ['curl', '-F', file_param , telemetry_url]
                proc = subprocess.Popen(['curl', '-F', file_param , telemetry_url],stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                cmd_out, cmd_err = proc.communicate()
                if cmd_out != None:
                    self.logger.post(cmd_out, 'DEBUG1')
                if cmd_err != None:
                    self.logger.post(cmd_err, 'DEBUG1')
            except Exception as e:
                self.logger.post("Couldn't submit telemetry logs")
                self.logger.post(str(e))

            # Remove files
            for logfile in logfiles:
                try:
                    os.remove(self.logdir + "/" + logfile)
                except Exception as e:
                    self.logger.post("Couldn't remove logfile " + self.logdir + "/" + logfile)
                    self.logger.post(str(e))
                    #print "Removed " + self.logdir + "/" + logfile
            try:
                os.remove(tarfileid)
                self.logger.post("Removed" + tarfileid)
            except Exception as e:
                    self.logger.post("Couldn't remove  " + tarfileid)
                    self.logger.post(str(e))
        else:
            self.logger.post("No telemetry files to submit.")