"""
     Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
     Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
     Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>


     Web site: http://www.astronomix.org/trac/Skylive-NG

     This file is part of Skylive-NG.

     Skylive-NG is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     Skylive-NG is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with Skylive-NG.  If not, see <http://www.gnu.org/licenses/>.
"""
import Image, ImageOps, ImageDraw, ImageFile
import platform
from skylive.utils import genutils as utils
import levels
import os
from cStringIO import StringIO
from Pycard import graphic
import numpy

class FitsImage:

   """ 
      this class rappresent a fits file image, and provide usefull
      functions to transform it to PIL for the viewer and others
      to manage fits reductions and transormations
   """

   canCompare = False
   pilResized = False

   def __init__(self, fits, remove=False, forceLowRes=False):
      import pyfits
      try:
         print 'Forced LowRew : ',forceLowRes
         self.fit = pyfits.open(fits)
         self.fit[0].verify('fix')
         if remove:
            try:
               os.unlink(fits)
            except:
               pass
      except:
         raise ValueError("Fits file "+str(fits)+" doesn't exists")
      self._getHeaders()
      self._getImageData()
      self._setCanCompare()
      self._setAutoLevels()
      if (platform.system() == 'Linux') and (utils.is_eeepc()) or forceLowRes:
         self._toPIL((400, 300))
      else:
         self._toPIL((800, 600))
      print "AUTOLEVELS: ", self.autoMinLevel, self.autoMaxLevel

   def _getHeaders(self):
      self.headers = self.fit[0].header
      try:
         self.ra = str(self.headers['OBJCTRA']).replace(":", "%20").replace(".", "%20")
         self.dec = str(self.headers['OBJCTDEC']).replace(".", "%20")
      except:
         self.ra = 0
         self.dec = 0
      try:
         self.yfield, self.xfield = self.headers['FOV'].replace(" ","").split("x")
      except:
         self.yfield, self.xfield = 32, 24


   def _getImageData(self):
      self.image = self.fit[0].data
      self.min = self.image.min()
      self.max = self.image.max()
      self.med = (self.min + self.max)/256



   def _toPIL(self, maxsize=False, scaletype='linear'):
      
      data = self.image
      ysize, xsize = data.shape
      ToResize = False
      self.percresize=100
      if maxsize:
         xmsize, ymsize = maxsize
         yresize = ysize
         xresize = xsize
         if xsize > xmsize:
            xresize = xmsize
            yresize = (ysize*xmsize)/xsize
            self.percresize = (xmsize*100)/xsize
            ToResize = True
         if yresize > ymsize:
            yresize = ymsize
            xresize = (xsize*ymsize)/ysize
            self.percresize = (ymsize*100)/ysize
            ToResize = True

      try:
         imgOr = Image.fromarray(data.astype("int32"), 'I', 0, -1)
      except:
         imgOr = Image.frombuffer("I", (xsize, ysize), data.astype("int32"), "raw", "I", 0, -1)

      # why all examples on internet show to get astype("b") (uint8) but we
      # need to get it as int32?
      #imgOr = Image.fromarray(data.astype("b"), 'L')
      #imgOr = Image.frombuffer("L", (xsize, ysize), data.astype("b"), "raw", "L", 0, 0)

      self.pilRaw = imgOr
      min,max = self.min, self.max

      med = self.med
      #scale = med / (max - min)
      #offset = -min * scale
      # changed to use autostretch values!
      #
      scale = med / (self.autoMaxLevel - self.autoMinLevel)
      offset = -self.autoMinLevel * scale
      #
      imgOrI = imgOr.point(lambda i: i * scale + offset)
      imgOrI = ImageOps.grayscale(imgOrI)
      self.pilOrI = imgOrI
      if ToResize:
         self.pilResized = True
         img = imgOrI.resize((xresize,yresize))
         img2 = imgOr #.resize((xresize,yresize))
         xsizeBit = xresize
         ysizeBit = yresize
      else:
         img = imgOrI
         xsizeBit = xsize
         ysizeBit = ysize

      self.pilImage = img
      self.xsizeBit = xsizeBit
      self.ysizeBit = ysizeBit

   def _setCanCompare(self):
      try:
         if 'OBJCTRA' in self.headers.ascardlist().keys():
            self.canCompare = True
            print 'CANCOMPARE TRUE'
      except:
            print 'EXCEPTION IN setCanCompare'
         

   def _setAutoLevels(self):
      self.autoMinLevel, self.autoMaxLevel = self.getAutoLevels()

   def getAutoLevels(self, method="zscale"):
      if method == 'zscale':
         return levels.zscale_levels(self.image, 0.1)
      elif method == 'percentile':
         return levels.percentile_levels(self.image)
      else:
         return levels.histogram_levels(self.image)


