"""Logic for pruning data

The requirement to prune data can occur in a few cases.  Time outs on transfers
or failed checksums are an obvious case.  We also use this section for clearing
the DAQ buffer copy.
"""

import datetime
import os
import shutil

from cax import config
from cax.task import Task
from cax.tasks import checksum


class RetryStalledTransfer(checksum.CompareChecksums):
    """Alert if stale transfer.

    Inherits from the checksum task since we use checksums to know when we
    can delete data.
    """

    # Do not overload this routine from checksum inheritance.
    each_run = Task.each_run

    def each_location(self, data_doc):
        if 'host' not in data_doc or data_doc['host'] != config.get_hostname():
            return  # Skip places where we can't locally access data

        if 'creation_time' not in data_doc:
            self.log.warning("No creation time for %s" % str(data_doc))
            return

        # How long has transfer been ongoing
        try:
            time_modified = os.stat(data_doc['location']).st_mtime
        except FileNotFoundError:
            time_modified = 0
        time_modified = datetime.datetime.fromtimestamp(time_modified)
        time_made = data_doc['creation_time']
        difference = datetime.datetime.utcnow() - max(time_modified,
                                                      time_made)

        if data_doc["status"] == "transferred":
            return  # Transfer went fine

        self.log.debug(difference)

        if difference > datetime.timedelta(hours=2):  # If stale transfer
            self.give_error("Transfer %s from run %d (%s) lasting more than "
                            "one hour" % (data_doc['type'],
                                          self.run_doc['number'],
                                          self.run_doc['name']))

        if difference > datetime.timedelta(hours=24) or \
                        (data_doc['host'] != 'xe1t-datamanager' and data_doc["status"] == 'error'):
            self.give_error("Transfer lasting more than 24 hours "
                            "or errored, retry.")

            self.purge(data_doc)

class RetryBadChecksumTransfer(checksum.CompareChecksums):
    """Alert if stale transfer.

    Inherits from the checksum task since we use checksums to know when we
    can delete data.
    """

    # Do not overload this routine from checksum inheritance.
    each_run = Task.each_run

    def each_location(self, data_doc):
        if 'host' not in data_doc or data_doc['host'] != config.get_hostname():
            return  # Skip places where we can't locally access data

        if data_doc["status"] != "transferred":
            return

        comparison = self.get_main_checksum(**data_doc)

        if comparison is None:
            return

        if data_doc['checksum'] != comparison:
            self.give_error("Bad checksum %d" % self.run_doc['number'])
            if self.check(data_doc['type'], warn=False) > 1:
                self.purge(data_doc)


class BufferPurger(checksum.CompareChecksums):
    """Purge buffer

    """

    # Do not overload this routine from checksum inheritance.
    each_run = Task.each_run

    def each_location(self, data_doc):
        """Check every location with data whether it should be purged.
        """
        # Skip places where we can't locally access data
        if 'host' not in data_doc or data_doc['host'] != config.get_hostname():
            return

        # Do not purge processed data
        # Warning: if you want to enable this here, need to add pax version checking in check()
        if data_doc['type'] == 'processed':
            self.log.debug("Do not purge processed data")
            return

        if data_doc['host'] == 'midway-login1':
            if self.run_doc['source']['type'] == "Kr83m" or self.run_doc['source']['type'] == "Rn220":
                self.log.debug("Do not purge %s data" % self.run_doc['source']['type'])
                return
        
        self.log.debug("Checking purge logic")

        # Only purge transfered data
        if data_doc["status"] != "transferred":
            self.log.debug("Not transfered")
            return

        # See if purge settings specified, otherwise don't purge
        if config.purge_settings() == None:
            self.log.debug("No purge settings")
            return

        # Require at least three copies of the data since we are deleting third.
        num_copies = self.check(data_doc['type'], warn=False)
        if num_copies < 3:
            self.log.debug("Not enough copies (%d)" % num_copies)
            return

        # The dt we require
        dt = datetime.timedelta(days=config.purge_settings())

        t0 = self.run_doc['start']
        t1 = datetime.datetime.utcnow()

        self.log.info(t1-t0 > dt)

        if t1 - t0 > dt:
            self.log.info("Purging %s" % data_doc['location'])
            self.purge(data_doc)

@@ -1418,34 +1418,71 @@
 == %22transferred%22
+ or data_doc%5B%22status%22%5D == %22verifying%22
 :%0A
-
             retu
@@ -1728,16 +1728,15 @@
    %22
-one
+2
  hour
+s
 %22 %25 
@@ -1942,39 +1942,144 @@
 =24)
- or %5C%0A                        (
+:%0A            self.give_error(%22Transfer lasting more than 24 hours, retry.%22)%0A            self.purge(data_doc)%0A            %0A        elif 
 data
@@ -2087,35 +2087,26 @@
 doc%5B
-'host'%5D != 'xe1t-datamanage
+%22status%22%5D == 'erro
 r' a
@@ -2121,29 +2121,37 @@
 doc%5B
-%22status%22%5D == 'erro
+'host'%5D != 'xe1t-datamanage
 r'
-)
 :%0A  
@@ -2190,68 +2190,18 @@
 fer 
-lasting more than 24 hours %22%0A                            %22or
+or process
  err
@@ -2215,17 +2215,16 @@
 etry.%22)%0A
-%0A
         

Update clear.py