from MultiSpectralFile import MultiSpectralFile
from hdf import *


class HDF4File:
  def __init__(self, filename):
    self.readerTable = None
    self.file = HDFfile( filename )

    file_info = self.file.fileinfo()
    self.num_datasets     = file_info[0]
    self.num_global_attrs = file_info[1]

    #- set-up dictionarys for variables/dimensions
    self.vars = {}
    self.dims = {}
    vv   = []

    for i in xrange(self.num_datasets):  # loop through all variables
      vv.append(self.file.select(i))

    for i in xrange(self.num_datasets):  # loop through all variables
      var  = vv[i]
      info =  var.getinfo()
      dim_names = []
      dim_lengths = []
      for j in xrange(info[1]):
        dim_id = var.getdimid(j)
        dim_info = self.file.diminfo(dim_id)
        self.dims[dim_info[0]] = dim_info[1]
        dim_names.append(dim_info[0])
        dim_lengths.append(dim_info[1])
      self.vars[info[0]] = [var, dim_names, dim_lengths]

  def getNumObsElements(self, name=None):
    if name != None:
      return self.dims[name]
    else:
      raise Exception, "must supply dimension name with this reader"
      
  def getNumObsLines(self, name=None):
    if name != None:
      return self.dims[name]
    else:
      raise Exception, "must supply dimension name with this reader"

  def getNumGeoElements(self, name=None):
    if name != None:
      return self.dims[name]
    else:
      raise Exception, "must supply dimension name with this reader"

  def getNumGeoLines(self, name=None):
    if name != None:
      return self.dims[name]
    else:
      raise Exception, "must supply dimension name with this reader"

  def getNumObsChannels(self, name=None):
    if name != None:
      return self.dims[name]
    else:
      raise Exception, "must supply dimension name with this reader"

  def getInstrumentName(self, name):
    atr_idx = self.file.findattr(name)
    return self.file.readattr(atr_idx)[2]

  def getTrackSegments(self, name=None):
    if name != None:
      if self.vars.has_key(name) == 1:
        return self.getValues(name)
      else:
        return None
    else:
      return None

  def getValues(self, name, start=None, size=None, stride=None):
    if self.vars.has_key(name) == 0:
      return None
    var = self.vars[name][0] # get the HDFvariable object from dictionary

    if start==None and size==None and stride==None:
      #-- read multi array (everything)
      start  = []
      stride = []
      size   = []
      dim_lengths = self.vars[name][2]
      rank = len(dim_lengths)
      for i in xrange(rank):
        start.append(0)
        stride.append(1)
        size.append(dim_lengths[i])
      return var.readdata(start, stride, size)[2]
    else: #- read (hyperslab) slice
      if stride == None:
        stride = []
        dim_lengths = self.vars[name][2]
        rank = len(dim_lengths)
        for i in xrange(rank):
          stride.append(1)
      return var.readdata(start, stride, size)[2]

  def getValue(self, name, start=None):
    if self.vars.has_key(name) == 1:
      var = self.vars[name][0]
      stride = []
      size   = []
      for i in xrange(len(start)):
        stride.append(1)
        size.append(1)
      return var.readdata(start, stride, size)[2]
    else:
      return None

  #- get scale/offset attribute for the observations variable
  def getObsScaleOffset(self, observation_name, scale_name, offset_name):
    if self.vars.has_key(observation_name) == 0:
      return None, None
    var = self.vars[observation_name][0]

    try:
      scaleAttr  = var.findattr(scale_name)
    except:
      scaleAttr = -1

    try:
      offsetAttr = var.findattr(offset_name)
    except:
      offsetAttr = -1

    if scaleAttr < 0:
      scale = None
    else:
      scale = var.readattr(scaleAttr)[2]

    if offsetAttr < 0:
      offset = None
    else:
      offset = var.readattr(offsetAttr)[2]

    return scale, offset

  def getObsDimOrder(self):
    var_dim_names = self.vars[self.readerTable.observation][1]
    dim_order = []
    #- assumed, default order
    dims_list = [self.readerTable.channelIndex, self.readerTable.obsElement, self.readerTable.obsLine]
    for dim_name in dims_list:
      for i in xrange(len(var_dim_names)):
        if var_dim_names[i] == dim_name:
          dim_order.append(i)
    return dim_order

  def getDimOrder(self, name, dims_list):
    var_dim_names = self.vars[name][1]
    dim_order = []
    for dim_name in dims_list:
      for i in xrange(len(var_dim_names)):
        if var_dim_names[i] == dim_name:
          dim_order.append(i)
    return dim_order

  #- verify that this <name> is a variable, dimension or attribute in the file
  def verifyName(self, name):
    if self.dims.has_key(name) == 1:
      return 1
    if self.vars.has_key(name) == 1:
      return 1
    return 0
