# Source code for drizzlepac.mdzhandler

    """
    This module supports the interpretation of the ``MDRIZTAB`` for
    processing as used in the pipeline.

    :Authors: Warren Hack, Ivo Busko, Christopher Hanley

    :License: `<http://www.stsci.edu/resources/software_hardware/pyraf/LICENSE>`_

    """
    from __future__ import division, print_function # confidence high

    import string, os

    from astropy.io import fits
    import numpy as np

    from stsci.tools import fileutil

    def getMdriztabParameters(files):
        """ Gets entry in MDRIZTAB where task parameters live.
            This method returns a record array mapping the selected
            row.
        """

        # Get the MDRIZTAB table file name from the primary header.
        # It is gotten from the first file in the input list. No
        # consistency checks are performed.
        _fileName = files[0]
        _header = fileutil.getHeader(_fileName)
        if 'MDRIZTAB' in _header:
            _tableName = _header['MDRIZTAB']
        else:
            raise KeyError("No MDRIZTAB found in file " + _fileName)

        _tableName = fileutil.osfn(_tableName)

        # Now get the filters from the primary header.
        _filters = fileutil.getFilterNames(_header)

        # Specifically check to see whether the MDRIZTAB file can be found
        mtab_path = os.path.split(_tableName)[0] # protect against no path given for _tableName
        if mtab_path and not os.path.exists(mtab_path): # check path first, if given
            raise IOError("Directory for MDRIZTAB '%s' could not be accessed!"%mtab_path)
        if not os.path.exists(_tableName): # then check for the table itself
            raise IOError("MDRIZTAB table '%s' could not be found!"%_tableName)

        # Open MDRIZTAB file.
        try:
            _mdriztab = fits.open(_tableName, memmap=False)
        except:
            raise IOError("MDRIZTAB table '%s' not valid!" % _tableName)

        # Look for matching rows based on filter name. If no
        # match, pick up rows for the default filter.
        _rows = _getRowsByFilter(_mdriztab, _filters)
        if _rows == []:
            _rows = _getRowsByFilter(_mdriztab, 'ANY')

        # Now look for the row that matches the number of images.
        # The logic below assumes that rows for a given filter
        # are arranged in ascending order of the 'numimage' field.
        _nimages = len(files)
        _row = 0
        for i in _rows:
            _numimages = _mdriztab[1].data.field('numimages')[i]
            if _nimages >= _numimages:
                _row = i
        print('- MDRIZTAB: AstroDrizzle parameters read from row %s.'%(_row+1))

        mpars = _mdriztab[1].data[_row]
        _mdriztab.close()

        interpreted = _interpretMdriztabPars(mpars)

        if "staticfile" in interpreted:
            interpreted.pop("staticfile")

        return interpreted

    def _getRowsByFilter(table, filters):
        rows = []
        for i in range(table[1].data.shape[0]):
            _tfilters = table[1].data.field('filter')[i]
            if _tfilters == filters:
                rows.append(i)
        return rows

    def _interpretMdriztabPars(rec):
        """
        Collect task parameters from the MDRIZTAB record and
        update the master parameters list with those values

        Note that parameters read from the MDRIZTAB record must
        be cleaned up in a similar way that parameters read
        from the user interface are.
        """
        tabdict = {}
        # for each entry in the record...
        for indx in range(len(rec.array.names)):
            # ... get the name, format, and value.
            _name = rec.array.names[indx]
            _format = rec.array.formats[indx]
            _value = rec.field(_name)

            # Translate names from MDRIZTAB columns names to
            # input parameter names found in IRAF par file.
            #
            #if _name.find('final') > -1: _name = 'driz_'+_name
            if _name in ['shiftfile','mdriztab']:
                continue
            drizstep_names = ['driz_sep_','final_']
            if _name in ['refimage','bits']:
                for dnames in drizstep_names:
                    tabdict[dnames+_name] = _value
                continue
            if _name in ['driz_sep_bits','final_bits']:
                tabdict[_name] = str(_value)
                continue
            if _name == 'coeffs':
                _val = True
                if _value in ['INDEF',None,"None",'',' ']: _val = False
                tabdict[_name] = _val
                continue

            par_table = {'subsky':'skysub','crbitval':'crbit','readnoise':'rdnoise'}
            if _name in par_table:
                _name = par_table[_name]

            # We do not care about the first two columns at this point
            # as they are only used for selecting the rows
            if _name != 'filter' and _name != 'numimages':
                # start by determining the format type of the parameter
                _fmt = findFormat(_format)

                # Based on format type, apply proper conversion/cleaning
                if (_fmt == 'a') or (_fmt == 'A'):
                    _val = cleanBlank(_value)
                    if _val is None:
                        _val = ''

                elif (_format == 'i1') or (_format=='1L'):
                    _val = toBoolean(_value)

                elif (_format == 'i4') or (_format == '1J'):
                    _val = cleanInt(_value)

                elif ('E' in _format) or (_format == 'f4') :
                    _val = cleanNaN(_value)

                else:
                    print('MDRIZTAB column ',_name,' has unrecognized format',_format)
                    raise ValueError
                if _name in ['ra','dec']:
                    for dnames in drizstep_names:
                        tabdict[dnames+_name] = _val

                else:
                    tabdict[_name] = _val

        return tabdict

    def toBoolean(flag):
        if (flag == 1):
            return True
        return False

    def cleanNaN(value):
        a = np.array(value)
    #    b = np.where(np.isnan(a))
        if np.any(np.isnan(a)): return None
        return float(value)

    def cleanInt(value):
        # THIS MAY BE MACHINE-DEPENDENT !!!
        if value == -2147483647:
        # Try to use 'sys.maxint' as value (WJH)
        #if value == -sys.maxint:
            return None
        return int(value)

    def cleanBlank(value):
        if value.strip() == '':
            return None
        return value

    def findFormat(format):
        # Parses record array format string for type
        _fmt = None
        for ltr in string.ascii_letters:
            if format.find(ltr) > -1:
                _fmt = ltr
                break
        return _fmt