import abc
import sys

from history.record import *
from history.ascfits import *
import numpy as np
from collections import namedtuple
from datetime import datetime

if sys.version_info < (3,):
    integer_types = (int, long, np.integer)
else:
    integer_types = (int, np.integer)

Parameters = namedtuple('Parameters', 'pkey pvalue pstack')


class HistoryRecord (Record): 

    def _get_afterkey(self):
        """
        This reference not currently in use in the History module.
        """
        # The afterkey string is a reference for pycrates to keep track of where the 
        # HistoryRecord is located in relation to standard keywords.

        return self._afterkey

    afterkey = property(_get_afterkey)

    def _get_content(self):
        """
        The string information for this HistoryRecord.
        """
        return self._content

    content = property(_get_content)

    def _get_tool(self):
        """
        The tool name.
        """
        return self._tool

    tool = property(_get_tool)

    def _get_datetime(self):
        """
        Date and time of when the HistoryRecord was created.
        Acceptable inputs are: 
           1) "" or None - no timestamp 
           2) "now"      - generates timestamp at runtime
           3) "YYYY-MM-DDThh:mm:ss" - date and time in correct format
        """
        return self.__datetime

    def _set_datetime(self, indate ):
        if indate is None or indate == "":
            self.__datetime = ""
        elif str(indate).lower() == "now":
            self.__datetime = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S")
        else:
            #check that date is in correct format
            datetime.strptime(indate, "%Y-%m-%dT%H:%M:%S")
            self.__datetime = indate

    datetime = property(_get_datetime)
    _datetime = property(_get_datetime, _set_datetime)

    def _get_params(self):
        """
        Returns a named tuple with the parameters the tool was run with.  
        ** NOTE: There must be an equal number of pkeys, pvalues, and pstacks lists.

        For example:
           pnames  = ["infile", "outfile", "tol"]
           pvalues = ["@in.lis", "out.fits", "tolerance"]
           pstacks = [ ["stkfile1.fits", "stkfile2.fits"], [], [] ]

        """
        if self._params is None:
            return None

        return {'pnames':self._params.pkey, 'pvalues':self._params.pvalue, 'pstacks':self._params.pstack}

    params = property(_get_params)

    def _get_asc_start(self):
        """
        The starting number of the ASC sequence.
        """
        return self.__asc_start

    def _set_asc_start(self, innum ):
        if isinstance(innum, integer_types) is False:
            raise TypeError("ASC start number must be an int or long")
        if innum < 0 or innum >= 100000:
            raise ValueError("ASC start value must be between 1 and 99999")
        self.__asc_start = innum

    asc_start = property(_get_asc_start)
    _asc_start = property(_get_asc_start, _set_asc_start)


    def __init__ (self, content=None, tool=None, date="now", param_names=[], param_values=[], param_stacks=None, asc_start=1):
        """
        Constructor for the HistoryRecord class.  Based on input, this will 
        generate one History record from either the content or the individual 
        arguments. 

        ** HistoryRecord attributes are immutable once created.
        
        Please see Appendix 3 - http://cxc.harvard.edu/ciao/data_products_guide/ascfits.ps
        for further reference on the ASC-FITS format.

        Parameters
        ----------
          content      : string or list of strings, required
                         Text information for this History record

            ** NOTE:  The format for ASC-FITS compliant content is as follows:
                      12345678901234567890........................................12345678901234567890
                      |_TAG__||__CONTENT_____________________________________________________________|
                      HISTORY  TOOL  :myTool  1998-07-29T00:00:00                             ASCnnnnn
                      HISTORY  PARM  :infile=myInputFile                                      ASCnnnnn
                      HISTORY  PARM  :outfile=myOutputFileyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyASCnnnnn
                      HISTORY  CONT  :yyyyyYYYY                                               ASCnnnnn
                                                                          ASC SEQUENCE NUMBER ^^^^^^^^
                               ^^^^ LABEL
                                     :^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ STRING VALUE                
            --OR--

          tool         : string, required
                         The tool name
          date         : string in format "YYYY-MM-DDThh:mm:ss", "now", "", or None, optional; default = "now"
                         Date and time of when the HistoryRecord was created
          param_names  : list of strings, inter-related with param_values and param_stacks; default = []
                         The parameter keys 
          param_values : list of values, inter-related with param_names and param_stacks; default = []
                         The parameter values
          param_stacks : list of lists containing strings, inter-related with param_names and param_values; default = None 
                         The parameter file stacks, if any
          asc_start    : integer, optional
                         The starting number of the ASC sequence

             **NOTE:  There must be an equal number of param_names, param_values, and param_stacks lists.
                      For example:
                          param_names  = ["infile", "outfile", "tol"]
                          param_values = ["@in.lis", "out.fits", "tolerance"]
                          param_stacks = [ ["stkfile1.fits", "stkfile2.fits"], [], [] ]

        Returns
        -------
          None
 
        Raises
        ------
          ValueError   : if record is empty
                         if both content and individual args are set
                         if no content and no tool name
                         if ASC-FITS record line is not in the expected ASC-FITS format
                         if trying to create more than one record
          TypeError    : if tool name is not a string
                         if parameter names is not a List
                         if parameter values is not a List
                         if parameter names are input but no corresponding values are given
                         if parameter values are input but no corresponding names are given
                         if length or parameter names List and values List are not equal
                         if parameter names List contains a datatype other than string
                         if parameter stacks is not a List of Lists
                         if parameter stacks are not the same length as names and values
                         if parameter stacks list elements contain a datatype other than string

        """
        self.__clear__()
        self.__tag = "HISTORY "

        # ASC_FITS Format class.
        self.__ascfits = ASCFITS()

        # if input args are empty, raise exception
        if content is None and tool is None and not param_names and not param_values:
            raise ValueError("Cannot create empty HistoryRecord; input content -OR- individual arguments are required.")

        # if both content and individual args are input, raise exception
        if content is not None and (tool is not None or len(param_names) > 0 or len(param_values) > 0):
            raise ValueError("Cannot create HistoryRecord from both content and individual arguments.")

        if content is not None:
            if not isinstance(content, list):
                content = [content]

            is_ascfits = self.__ascfits.is_compliant( content[0] )
            if is_ascfits is False and len(content) > 1:
                raise ValueError("Cannot create more than one history record")     

            self.__parse(content, is_ascfits)
        else :

            if tool is None or len(tool) == 0:
                raise ValueError("Cannot create a HistoryRecord without a tool name")
            if isinstance(tool, str if sys.version_info[0] >= 3 else basestring) is False:
                raise TypeError("The tool name must be a string")

            self._tool = tool
            self._datetime = date
        
            # set up pstack to have the same number of items as in pnames
            if param_stacks is None:
                param_stacks = [[]]*len(param_names)
            
            # pvalues may be a list of arbitrary datatype values; convert to list of strings 
            param_values = ([str(x) for x in param_values])

            # check Parameters before storing
            self.__check_params(param_names, param_values, param_stacks)
            self._params = Parameters(param_names, param_values, param_stacks)

            self._asc_start = asc_start


    def __check_params(self, param_names, param_values, param_stacks):
        """
        Private helper method for performing value checking and type checking on
        input parameters.  If no Exception is raised, then inputs are valid.

        Parameters
        ----------
          param_names  : list of strings, required, inter-related with param_values and param_stacks
                         The parameter keys 
          param_values : list of strings, required, inter-related with param_names and param_stacks
                         The parameter values
          param_stacks : list of lists containing strings, required, inter-related with param_names and param_values
                         The parameter file stacks, if any

        Returns
        -------
          None
 
        Raises
        ------
          TypeError    : if parameter names is not a List
                         if parameter values is not a List
                         if parameter names are input but no corresponding values are given
                         if parameter values are input but no corresponding names are given
                         if length or parameter names List and values List are not equal
                         if parameter names List contains a datatype other than string
                         if parameter stacks is not a List of Lists
                         if parameter stacks are not the same length as names and values
                         if parameter stacks list elements contain a datatype other than string

        """
        # check parameter names and values
        if not isinstance(param_names, list):
            raise TypeError("Parameter names must be a list")

        if not isinstance(param_values, list):
            raise TypeError("Parameter values must be a list")

        if len(param_names) != len(param_values):
            if len(param_values) != 0 and len(param_names) == 0:
                raise ValueError("Parameter names list is required")
            elif len(param_names) != 0 and len(param_values) == 0:
                raise ValueError("Parameter values list is required")
            else:
                raise ValueError("Parameter names and values lists must be the same length")

        if all(isinstance(xx, str if sys.version_info[0] >= 3 else basestring) for xx in param_names) is False:
            raise TypeError("All parameter names must be strings")

        # param_values are all converted to strings before this method is called - check no longer necessary
        #if all(isinstance(xx, str if sys.version_info[0] >= 3 else basestring) for xx in param_values) is False:
        #    raise TypeError("All parameter values must be strings")

        # check parameter stacks
        if len(param_names) != len(param_stacks):
            raise ValueError("Parameter stacks list must be the same length as names and values lists")

        if param_stacks is not None and len(param_stacks) > 0:
            for stk in (param_stacks):
                if not isinstance(stk, list):
                    raise TypeError("Parameter stacks list must be a List of Lists")

                if all(isinstance(xx, str if sys.version_info[0] >= 3 else basestring) for xx in stk) is False:
                    raise TypeError("All parameter stacks must be strings")


    def __parse(self, lines, is_ascfits):
        """
        This private helper method processes the content lines and stores the 
        information in the HistoryRecord's tool, date, parameters, and asc_start 
        attributes.

        Parameters
        ----------
          lines       : string or list of strings
                        Text information for this History record
        
        Returns
        -------
          None
 
        Raises
        ------
          ValueError   : if ASC-FITS record line is not in the expected ASC-FITS format
                         if trying to create more than one record

        """

        parmstr=""
        stckstr=""
        parm = False
        stck = False
        pixlib = False
        ardlib = False
        stack = []
        count = 0  # keeps track of how many records have been read in
        param_names  = []
        param_values = []
        param_stacks = []

        # for non-ASC-FITS compliant history, set content and return
        if is_ascfits is False:
            line = lines[0]
            if line.startswith( self.__tag ): # strip tag if present
                self._content = line[len(self.__tag):]
            else:
                self._content = line
            return

        # assumes this is an ASC-FITS record
        lines.append("EOF")
        for line in lines:

            # if not EOF, check the line length and format
            if "EOF" not in line: 
                if self.__ascfits.is_compliant( line ) is False:
                    raise ValueError("non-compliant card found in ASC-FITS content: "+line)

            #for ASC-FITS compliant history with TOOL, PARM, STCK, CONT
            if self.__ascfits.label( line ) == self.__ascfits.TOOL_TOKEN:
                self._tool = self.__ascfits.tool( line )
                self._datetime = self.__ascfits.version( line )

                count += 1
                if count > 1:
                    raise ValueError("Cannot create more than one history record")

                self._asc_start = self.__ascfits.seqno( line )

            # flush param or stack and reset
            if (self.__ascfits.label( line ) in [self.__ascfits.PARM_TOKEN,self.__ascfits.STCK_TOKEN]) or "EOF" in line:
                if parm is True and parmstr != "":
                    if ardlib or (pixlib and ("***" in parmstr or ".par" in parmstr)) :
                        key = parmstr
                        val = ""
                    else:
                        (key, val) = parmstr.split("=",1)
                        if val == "":
                            val = " "

                    param_names.append( key )
                    param_values.append( val )
                    parm = False
                    parmstr = ""

                elif stck is True:
                    stack.append(stckstr)
                    stckstr = ""                    
                    
                    if (self.__ascfits.label( line ) == self.__ascfits.PARM_TOKEN) or "EOF" in line:
                        param_stacks[-1] = stack
                        stack = []
                        stck = False

            if self.__ascfits.label( line ) == self.__ascfits.PARM_TOKEN:
                parm = True
                    
                # Check for special cases
                #if "ARDLIB Version" in line:
                if (self.__ascfits.tool( line ) == "ARDLIB" )and(self.__ascfits.version( line ).startswith("Version") ):
                    self._tool = self.__ascfits.body( line ).rstrip()       # set tool to full body content
                    self._asc_start = self.__ascfits.seqno( line )
                    ardlib = True
                    count += 1
                elif (self.__ascfits.tool( line ) == "PIXLIB" )and(self.__ascfits.version( line ).startswith("Version") ):
                    self._tool = self.__ascfits.body( line ).rstrip()       # set tool to full body content
                    self._asc_start = self.__ascfits.seqno( line )
                    pixlib = True
                    count += 1
                else:
                    parmstr += self.__ascfits.body( line ).strip()

                if count > 1:
                    raise ValueError("Cannot create more than one history record")

                param_stacks.append([])

            if self.__ascfits.label( line ) == self.__ascfits.STCK_TOKEN:
                stck = True
                stckstr += self.__ascfits.body( line ).strip()

            if self.__ascfits.label( line ) == self.__ascfits.CONT_TOKEN:
                if parm:
                    if len(self.__ascfits.body( line ).strip()) == 0:
                        parmstr += " "
                    else:
                        parmstr += self.__ascfits.body( line ).strip()
                elif stck:
                    if len(self.__ascfits.body( line ).strip()) == 0:
                        stckstr += " "
                    else:
                        stckstr += self.__ascfits.body( line ).strip()


        # set Parameters gathered in for-loop
        self._params = Parameters(param_names, param_values, param_stacks)

        # remove EOF
        del lines[-1]


    def __clear__(self):
        self._tool = ""
        self.__datetime = ""
        self._params = None
        self.__asc_start = 1
        self._afterkey = ""
        self._content = ""
        self.__ascfits = None


    def __str__(self):
        return self.__repr__()


    def __repr__(self):
        strrepr = ''

        if self._content != "" or self._tool == "":
            strrepr +=  "Content:    '" + self._content + "'\n"

        else: 
            strrepr +=  "Tool:  " + self._tool + "\n"
            strrepr +=  "Date:  " + self.__datetime + "\n"
            strrepr +=  "Params:" + "\n"

            if self._params is not None:
                plen = len(self._params.pkey)
                
                for ii in (range(0, plen)):
                    strrepr +=  "   " + self._params.pkey[ii]
                    if self._params.pvalue[ii] != "":
                        strrepr += " = " + self._params.pvalue[ii]
                    strrepr += "\n"
                    try:
                        for jj in (range(0, len(self._params.pstack[ii]))):
                            strrepr +=  "      > " + self._params.pstack[ii][jj] + "\n"
                    except:
                        pass

            strrepr +=  "ASCNUM:  " + str(self.__asc_start) + "\n"

        return strrepr


    def __del__(self):
        self.__clear__()


    def as_ASC_FITS( self, with_tag=False, stk_expand=False ):
        """
        Returns HistoryRecord attributes as an ASC-FITS formatted string.

        Parameters
        ----------
          with_tag     : boolean, default = False
                         Flag indicating if 'HISTORY' tag should be included
                         in output
          stk_expand   : boolean, default = False
                         Flag to control whether parameter stacks (if any) should be 
                         included in the output
        
        Returns
        -------
          ascstring    : string
                         HistoryRecord content as an ASC-FITS formatted string 

        Raises
        ------
          RuntimeError : if trying to print a non-ASC-FITS compliant record

        Example
        -------
          If tag=True, returns formatted string for each record with tag, e.g.
            HISTORY  TOOL  :dmhedit  2016-08-11T20:43:33                            ASC00870
            HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00871
            HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_psf3.fits[ASC00872
            HISTORY  CONT  :PSF]                                                    ASC00873
            HISTORY  PARM  :filelist=                                               ASC00874
            HISTORY  PARM  :operation=add                                           ASC00875
            HISTORY  PARM  :key=BIN                                                 ASC00876
            HISTORY  PARM  :value=4                                                 ASC00877
            HISTORY  PARM  :datatype=string                                         ASC00878
            HISTORY  PARM  :unit=                                                   ASC00879
            HISTORY  PARM  :comment=                                                ASC00880
            HISTORY  PARM  :verbose=0                                               ASC00881

          If tag=False, returns formatted string for each record without tag, e.g.
             TOOL  :dmhedit  2016-08-11T20:43:33                            ASC00870
             PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00871
             CONT  :87231988n944/output/acisf05017_000N022_r0001b_psf3.fits[ASC00872
             CONT  :PSF]                                                    ASC00873
             PARM  :filelist=                                               ASC00874
             PARM  :operation=add                                           ASC00875
             PARM  :key=BIN                                                 ASC00876
             PARM  :value=4                                                 ASC00877
             PARM  :datatype=string                                         ASC00878
             PARM  :unit=                                                   ASC00879
             PARM  :comment=                                                ASC00880
             PARM  :verbose=0                                               ASC00881

        """

        if len(self._content) > 0 or self._tool == "":
            raise RuntimeError("Unable to print non-ASC-FITS compliant history in ASC-FITS format.")

        retlist = []
        tmpstr = ""
        tagstr = ""
        
        spcstr   = "  "
        toolstr  = " TOOL" + spcstr + ":"
        paramstr = " PARM" + spcstr + ":"
        stackstr = " STCK" + spcstr + ":"
        contstr  = " CONT" + spcstr + ":"

        paramset = []
        for ii in range (0, len(self._params.pkey) ):
            pentry = [self._params.pkey[ii], self._params.pvalue[ii], self._params.pstack[ii] ]
            paramset.append(pentry)

        # Generate cards from content
        cards = self.__ascfits.as_cards( self._tool, self.__datetime, paramset, self.__asc_start, with_tag=with_tag, expand_stacks=stk_expand )

        return '\n'.join(cards)


    def as_FITS(self, with_tag=False):
        """
        Returns HistoryRecord attributes as a FITS formatted string.
        If the content would generate FITS keyword cards > 80 chars,
        the content is split into multiple lines using the newline char.

        Parameters
        ----------
          with_tag     : boolean, default = False
                         Flag indicating if 'HISTORY' tag should be included
                         in output

        Returns
        -------
          fits_string  : string
                         HistoryRecord content as an FITS formatted string 

        Raises
        ------
          RuntimeError : if trying to print FITS with no tool name
                         

        Example
        -------
          If tag=True:
            HISTORY dmhedit infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988
            HISTORY n944/output/acisf05017_000N022_r0001b_psf3.fits[PSF] filelist= operation
            HISTORY =add key=BIN value=4 datatype=string unit= comment= verbose=0           

          If tag=False:
            dmhedit infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988
            n944/output/acisf05017_000N022_r0001b_psf3.fits[PSF] filelist= operation
            =add key=BIN value=4 datatype=string unit= comment= verbose=0  

        """
        result   = ""
        cardsize = 80
        tagsize  = 8                   # TAG uses chars 1:8
        nchars   = cardsize - tagsize  # Text in chars  9:80

        if "PIXLIB" in self._tool or "ARDLIB" in self._tool:
            return self.as_ASC_FITS(with_tag)

        if with_tag:
            # add tag to each line
            prefix = '{:{width}}'.format( self.__tag, width=tagsize)
        else:
            prefix = ""

        content= ""
        if len(self.content) > 0 or self._tool == "":
            content = self.content
        else:
            content = self.as_command()

        # Wrap content if needed so total card length is <= FITS card length
        if len(content) > nchars:
            parts = list( content[0+ii:nchars+ii] for ii in range(0, len(content), nchars) )
        else:
            parts = [content]

        # Make each line proper length, adding tag as requested
        for ii in range(0,len(parts)):
            tmpstr = prefix + '{:{width}}'.format(parts[ii], width=nchars)
            parts[ii] = tmpstr

        # Build final result string
        result = "\n".join(parts)

        return result


    def as_string(self, with_tag=False):
        """
        Returns HistoryRecord attributes as a string.
        Where format = [<tag>]+<content>

        Parameters
        ----------
          with_tag     : boolean, default = False
                         Flag indicating if 'HISTORY ' tag should be included
                         in output

        Returns
        -------
          a_string     : string
                         HistoryRecord attributes as an FITS formatted string 

        Raises
        ------
          RuntimeError : if trying to print string with no tool name

        Example
        -------
          If tag=True:
            HISTORY dmhedit infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_psf3.fits[PSF] filelist= operation=add key=BIN value=4 datatype=string unit= comment= verbose=0 

          If tag=False:
            dmhedit infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_psf3.fits[PSF] filelist=  operation=add key=BIN value=4 datatype=string unit=  comment=  verbose=0   

        """
        retstr = ""
        tmpstr = ""
        tagstr = ""

        if with_tag:
            tagstr = self.__tag

        if len(self._content) > 0 or self._tool == "":
            tmpstr += tagstr + self._content
        else:
            if "PIXLIB" in self._tool or "ARDLIB" in self._tool:
                tmpstr += tagstr + self._tool + "\n"

                if self._params is not None:
                    plen = len(self._params.pkey)
                
                    for ii in (range(0, plen)):
                        tmpstr += tagstr + self._params.pkey[ii]
                        if len(self._params.pvalue[ii]) > 0:
                            tmpstr += " = " + self._params.pvalue[ii]
                        tmpstr += "\n"

            else:
                tmpstr += tagstr + self.as_command()

        return tmpstr


    def as_command( self ):
        """
        If the HistoryRecord is an ASC-FITS compliant record, returns the record in
        line-command format.

        Parameters
        ----------
          None
        
        Returns
        --------
          command      : string
                         HistoryRecord attributes in line-command format
 
        Raises
        ------
          RuntimeError : if trying to print pixlib history record as command
                         if trying to print ardlib history record as command
                         if attempting to print non-ASC-FITS compliant history as command
                         if trying to print command with no tool name

        Example
        -------
          If the input is:

            HISTORY  TOOL  :dmhedit   2016-08-11T20:43:33                           ASC00870
            HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00871
            HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_psf3.fits[ASC00872
            HISTORY  CONT  :PSF]                                                    ASC00873
            HISTORY  PARM  :filelist=                                               ASC00874
            HISTORY  PARM  :operation=add                                           ASC00875
            HISTORY  PARM  :key=BIN                                                 ASC00876
            HISTORY  PARM  :value=4                                                 ASC00877
            HISTORY  PARM  :datatype=string                                         ASC00878
            HISTORY  PARM  :unit=                                                   ASC00879
            HISTORY  PARM  :comment=                                                ASC00880
            HISTORY  PARM  :verbose=0                                               ASC00881

          Then the output would be:
            dmhedit infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_psf3.fits[PSF] filelist=  operation=add key=BIN value=4 datatype=string unit=  comment=  verbose=0   

        """

        if len(self._content) == 0 and len(self._tool) == 0:
            return  # record with an empty line

        if len(self._content) > 0:
            raise RuntimeError("Unable to print non-ASC-FITS compliant history as command.")

        if len(self._tool) == 0:
            raise RuntimeError("Unable to print command without a tool name.")

        if "PIXLIB" in self._tool:
            raise RuntimeError("Unable to print PIXLIB history as command.")

        if "ARDLIB" in self._tool:
            raise RuntimeError("Unable to print ARDLIB history as command.")

        tmpstr = self._tool + " "

        if self._params is not None:
            plen = len(self._params.pkey)

            for ii in (range(0, plen)):
                if len(self._params.pkey[ii]) == 0:
                    tmpstr += self._params.pvalue[ii] + " "
                else:
                    tmpstr += self._params.pkey[ii] + "=" + self._params.pvalue[ii] + " "

        return tmpstr


    def is_ascfits_compliant( self ):
        """
        Returns true if the record is ASC-FITS compliant, false if record is 
        not compliant, empty, or contains PIXLIB/ARDLIB information.

        Parameters
        ----------
          None
        
        Returns
        -------
          is_compliant : boolean
                         True, if record is compliant
                         False, if record is not compliant, empty, or 
                                contains PIXLIB/ARDLIB information  
 
        Raises
        ------
          None

        """

        # if content contains something, record is not ASC-FITS compliant
        if len(self._content) != 0:
            return False

        # if record is empty or contains PIXLIB info, record is not ASC-FITS compliant
        if (len(self._tool) == 0 and len(self._content) == 0) or "PIXLIB" in self._tool.upper() or "ARDLIB" in self._tool.upper():
            return False

        return True
        
