from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import datetime
from DIRAC.Core.Utilities.JEncode import JSerializable


class FTS3File(JSerializable):
    """This class represents an a File on which a given Operation
    (Transfer, Staging) should be executed
    """

    # START states
    ALL_STATES = [
        "New",  # Nothing was attempted yet on this file
        "Submitted",  # From FTS: Initial state of a file as soon it's dropped into the database
        "Ready",  # From FTS: File is ready to become active
        "Active",  # From FTS: File went active
        "Finished",  # From FTS: File finished gracefully
        "Canceled",  # From FTS: Canceled by the user
        "Staging",  # From FTS: When staging of a file is requested
        "Failed",  # From FTS: File failure
        "Defunct",  # Totally fail, no more attempt will be made
        "Started",  # From FTS: File transfer has started
        "Not_used",  # From FTS: Transfer not being considered yet, waiting for another one (multihop)
        "Archiving",  # From FTS: file not yet migrated to tape
    ]

    # These are the states that we consider final.
    # No new attempts will be done on our side for
    # FTS3Files reaching one of these
    # Note that Canceled is not final state, because
    # FTS fails some transfers as "Canceled" (gsiftp timeout)

    FINAL_STATES = ["Finished", "Defunct"]

    FTS_SUCCESS_STATES = ["Finished"]
    FTS_FAILED_STATES = ["Canceled", "Failed"]

    # These are the states that the fts servers consider final.
    # No new attempts will be done on their side, but we can
    # still retry.
    FTS_FINAL_STATES = FTS_SUCCESS_STATES + FTS_FAILED_STATES
    INIT_STATE = "New"

    # END states

    _attrToSerialize = [
        "fileID",
        "operationID",
        "status",
        "attempt",
        "creationTime",
        "lastUpdate",
        "rmsFileID",
        "checksum",
        "size",
        "lfn",
        "error",
        "targetSE",
        "ftsGUID",
    ]

    def __init__(self):

        self.status = FTS3File.INIT_STATE
        self.attempt = 0

        now = datetime.datetime.utcnow().replace(microsecond=0)

        self.creationTime = now
        self.lastUpdate = now

        self.rmsFileID = 0
        self.checksum = None
        self.size = 0

        self.lfn = None
        self.error = None

        self.targetSE = None

        # Place holder for the latest job taking care of this file
        self.ftsGUID = None

    @staticmethod
    def fromRMSFile(rmsFile, targetSE):
        """Returns an FTS3File constructed from an RMS File.
        It takes the value of LFN, rmsFileID, checksum and Size

        :param rmsFile: the RMS File to use as source
        :param targetSE: the SE target

        :returns: an FTS3File instance
        """
        ftsFile = FTS3File()
        ftsFile.lfn = rmsFile.LFN
        ftsFile.rmsFileID = rmsFile.FileID
        ftsFile.checksum = rmsFile.Checksum
        ftsFile.size = rmsFile.Size
        ftsFile.targetSE = targetSE

        return ftsFile
