import abc
import sys
from history.record import *

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

        return self._afterkey

    afterkey = property(_get_afterkey)

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

    content = property(_get_content)


    def __init__ (self, content=None, is_blank=False):
        """        
        Constructor for the CommentRecord class.  
        This will generate one Comment record based on the input content.

        ** CommentRecords are immutable once created.

        Parameters
        ----------
          content      : string
                         Text information for this Comment record.
                         Expected format: (COMMENT\s\s)?.*
                           o 0 or 1 tag "COMMENT  "
                           o followed by 0 or more characters of content
                         The tag, if provided, is stripped from the input,
                         storing the remaining content.

          is_blank     : boolean, default=False
                         Used to create a completely BLANK comment record.
                         If True, no content may be provided.

        Returns
        -------
          None       
 
        Raises
        ------
          TypeError    : if provided content is not string type
          ValueError   : if content provided with is_blank=True

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

        self._is_blank = is_blank

        if content is not None:
            if not isinstance(content, str if sys.version_info[0] >= 3 else basestring):
                raise TypeError("'content' argument must be string type.")

            if is_blank:
                raise ValueError("Can not provide 'content' when is_blank=True.")

            self.__parse(content)



    def __parse(self, line):
        """
        This private helper method processes the content line and stores the 
        information in the CommentRecord's content attribute.

        Parameters
        ----------
          line         : string
                         Text information for this Comment record
        
        Returns
        -------
          None

        Raises
        ------
          None       

        """
        if line.startswith( self.__tag ): # strip tag if present
            self._content = line[len(self.__tag):]
        else:
            self._content = line
            

    def __clear__(self):
        self._afterkey = ""
        self._content = ""
        self._is_blank = False


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


    def __repr__(self):
        strrepr = ''

        if self._is_blank:
            strrepr +=  "Content:    <Completely BLANK Line>\n"
        else:
            strrepr +=  "Content:    '" + self._content + "'\n"

        return strrepr


    def __del__(self):
        self.__clear__()


    def as_string( self, with_tag=False ):
        """
        Returns the CommentRecord content in a formatted string.
        Where format = [<tag>]+<content>

        Parameters
        ----------
          with_tag     : boolean, default = False
                         Flag indicating if 'COMMENT  ' tag should be included
                         in output
        
        Returns
        -------
          result       : string
                         CommentRecord content as a formatted string 
                         
        Raises
        ------
          None

        Example
        -------
          If with_tag=True, returns formatted string for each record with tag

            => "COMMENT   ------- Observation Information -------              "

	  -OR-

          If with_tag=False, returns formatted string for each record without tag

	    => " ------- Observation Information -------              "

        """
        result = ""

        if with_tag and not self._is_blank:
            result += self.__tag

        result += self._content

        return result


    def as_FITS( self, with_tag=False ):
        """
        Returns the CommentRecord content in 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.

        The FITS Version 3.0 standard specification for COMMENT keywords 
        is covered in Sections 4.1.2 and 4.4.2.4.  In summary:
          name:    bytes 1 through 8 == 'COMMENT '
          content: bytes 9 through 80 should be interpreted as commentary text

        Parameters
        ----------
          with_tag     : boolean, default = False
                         Flag indicating if 'COMMENT  ' tag should be included.
                         This facilitates usage as a complete FITS card, or 
                         with just the content to use with various write_key 
                         methods.

        Returns
        -------
          result       : string
                         CommentRecord content as a formatted string 
                         
        Raises
        ------
          None

        Example
        -------
          If tag=True, returns formatted string for each record with tag, e.g.
          #   00000000011111111112222222222333333333344444444445555555555666666666677777777778
          #   12345678901234567890123456789012345678901234567890123456789012345678901234567890
          => "COMMENT   ------- Observation Information -------                               "

	  -OR-

          If tag=False, returns formatted string for each record without tag, e.g.
          => "  ------- Observation Information -------                               "

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

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

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

        #print "Content Before Adjusting Lengths"
        #print "00000000011111111112222222222333333333344444444445555555555666666666677777777778"
        #print "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
        #for item in parts:
        #    print "XXXXXXXX"+item+"XX"

        # 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

        #print "Content After Adjusting Lengths"
        #print "00000000011111111112222222222333333333344444444445555555555666666666677777777778"
        #print "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
        #for item in parts:
        #    if with_tag:
        #        print item+"XX"
        #    else:
        #        print "XXXXXXXX"+item+"XX"

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

        return result
