import sys
import os
import unittest
import pidly
import glob
import numpy as np
from astropy.io import fits
from test_helper import TestHelper


class IdlTestCases(unittest.TestCase, TestHelper):
  """
  Collection of tests for Ivan Katkov's IDL routines for SDSS spectral fitting and profile decomposition.
  
  Run all tests as:
    > python test_idl_fit.py
  Run single test `test_window` as:
    > python -m unittest test_idl_fit.IdlTestCases.test_window
  """
  # settings
  # nothing here yet
  
  @classmethod
  def setUpClass(self):
    """
    Setup test environment before all tests
    """
    # self.idl = pidly.IDL('/usr/local/bin/idl')
    self.idl = pidly.IDL()
    # !path initialization just like in IK's start.pro
    self.idl("paths = ['+/usr/local/itt/idl/external/']")
    self.idl("paths = [ paths, '+/home/katkov/sci/IDL_libs/']") # @TODO: fix
    self.idl("paths = [ paths, '+/usr/local/itt/idl/external/idlutils/goddard/pro/']")
    self.idl("paths = [ paths, '+/usr/local/itt/idl/external/idlutils/pro/']")
    self.idl("paths = [ paths, '+/usr/local/itt/idl/external/izi/']")
    self.idl("paths = [ paths, '+/home/katkov/sci/IDL_libs/Spextool/'    ]") # @TODO: fix
    self.idl("paths = [ paths, '+~/sci/IDL_libs/astron_v55/']") # @TODO: fix
    self.idl("paths = [ paths, '+~/sci/IDL_libs/mpfit/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/libCOYOTE/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/ULySS/v1.3/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/izi/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/local_nburst/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/my_pro/']")
    self.idl("paths = [ paths, '+~/sci/IDL_libs/scorpio_reduction/']")

    self.idl("for i=0,n_elements(paths)-1 do !path=!path+':'+EXPAND_PATH(paths[i])")
    self.idl('.comp ../adaptive_window.pro') # @TODO: abs path to adaptive_window.pro
    self.idl('.comp ../collect_results_nonpar.pro') # @TODO: abs path to collect_results_nonpar.pro
    
  
  @classmethod
  def tearDownClass(self):
    """
    Clean test environment after all tests
    """
    self.idl.close()
 
  ######### TESTS BELOW #########  
  
  def test_idl_simple(self):
    """
    Simplest test of pidly
    """
    self.idl('x = total([1, 1], /int)')
    self.assertEqual(self.idl.x, np.array(2), 'Wrong total() result')
    

  @unittest.skip("waiting for IK fix: add argument for test_window to accept settings.TEST_AGN_SPECTRA_PATH; also think about calling test_window by abs path ")
  def test_window(self):
    """
    """
    print '\n********** testing adaptive window **********'
    self.idl("test_window, '%s', count_fails=count_fails,verbose=1" % settings.TEST_AGN_SPECTRA_LIST)
    self.assertEqual(self.idl.count_fails, 0)


  @unittest.skip("waiting for IK fix: add argument for collect_results_nonpar to accept settings.TEST_BAD_FITS_PATH; also think about calling collect_results_nonpar by abs path")
  def test_collect_nonpar(self):
    """
    """
    print '\n********** testing collecting tables **********'
    idl_command = "collect_results_nonpar, '{}', '{}',nbad=nbad".format(self.TEST_BAD_FITS_LIST,'test_fits/restable_nonpar.fits')
    print 'IDL comand: ', idl_command
    self.idl( idl_command )
    self.assertEqual(self.idl.nbad, 4)


  def test_scoop_collect_data(self):
    """
    Test multiproc.py:collect_data() worker function
    """
    try:
      tmp_filelist = make_file_list(mask='fit_agn/04??')
      # args to scoop.map is like [(0, 4, 'filename', 'function_name'), (1, 4, 'filename', 'function_name'), (2, 4, ...), ...]
      # so use one tuple here
      data = collect_data((0, 8, tmp_filelist, 'collect_data'))
      self.assertGreater(len(data), 100)
    finally:
      os.unlink(tmp_filelist)
    
    
if __name__ == '__main__':
    # we can't easily make emission-line-fitting a package, so no relative imports, have to hack sys.path to import local code
    sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
    import settings
    from multiproc import collect_data, make_file_list
    
    unittest.main()
    