#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

from optparse import OptionParser
import os,sys
import glob


from pNbody import *
from pNbody.param import Params

def parse_options():

  usage = "usage: %prog [options] file"
  parser = OptionParser(usage=usage)



  parser.add_option("-p",
  		    action="store", 
  		    dest="parameterfile",
  		    type="string",
		    default = None,   
  		    help="parameterfile file",       
  		    metavar=" FILE")    

  parser.add_option("-o",
  		    action="store", 
  		    dest="outputfile",
  		    type="string",
		    default = 'film.gmv',   
  		    help="output file",       
  		    metavar=" FILE")    

  parser.add_option("-d",
  		    action="store", 
  		    dest="directory",
  		    type="string",
		    default = None,   
  		    help="directroy containing files",       
  		    metavar=" DIRECTORY")    


  parser.add_option("--pio",
  		    action="store_true", 
  		    dest="pio",
		    default = False,   
  		    help="parallele io",       
  		    metavar=" BOOL")  
		    
  parser.add_option("--mkfits",
  		    action="store_true", 
  		    dest="mkfits",
		    default = True,   
  		    help="create fits outputs",       
  		    metavar=" BOOL") 		    
		    
  parser.add_option("--fitsdir",
  		    action="store", 
  		    dest="fitsdir",
  		    type="string",
		    default = 'fits',   
  		    help="outputdirectory for fits files",       
  		    metavar=" DIRECTORY")  		    
		    

  parser.add_option("--shape",
		   action="store", 
		   dest="shape",
		   type="string",
		   default = None,		   
		   help="shape (x,y)",	 
		   metavar=" STRING")   


  (options, args) = parser.parse_args()
  files = args
  
  return files,options


def InitParameters(nh,nw):
   
  params    = []
  
  for i in range(nh*nw):
    
    param = {}
    
    # read default pNbody parameters
    gparams = Params(PARAMETERFILE,None)
    # create new params
    for p in gparams.params:
      param[p[0]]=p[3]    
    
    
    # geometry parameters  
    #param['obs']=None
    #param['x0']=None
    #param['xp']=None
    #param['alpha']=0
    #param['view']='xy'
    #param['size']=(150,150)
    #param['mode']='m'
    #param['filter_name'] = None
    #param['filter_opts'] = None
    #param['scale'] = 'log'
    #param['mn'] = 0
    #param['mx'] = 0
    #param['cd'] = 0
    #param['frsp'] = 0.

    
    # additionnal default parameters
    
    param['id'] = i
    
    param['tdir']=None
    param['pfile']=None
    
    param['components']=['all']
    
    param['ftype'] = 'gadget'
    param['time'] = 'nb.atime'
    
    param['exec'] = None
    param['macro'] = None
    param['select'] = None
    
  
    params.append(param)
    
  return params




def ReadNbodyParameters(paramname):
  '''
  read param from a parameter Nbody file
  '''
  
  gparams = Params(paramname,None)
  
  param = {}
  # create new params
  for p in gparams.params:
    param[p[0]]=p[3]    

  return param



#######################################################################
#
#	M A I N
#
#######################################################################


files,opt = parse_options()

if opt.parameterfile==None:
  print "you must specify a parameter file"
  sys.exit()
  
if not os.path.exists(opt.parameterfile):
  print "file %s does not exists"%opt.parameterfile
  sys.exit()

if opt.mkfits:
  if not os.path.exists(opt.fitsdir):
    os.mkdir(opt.fitsdir)



##############################
# read parameter file
##############################

execfile(opt.parameterfile) 


##############################
# create files
##############################




if len(files)==0:
  
  print "no files defined, using tdir"
  
  # check that all frame have tdir
  for param in params:
    if param['tdir']==None:
      print "frame %d does not have 'tdir' defined "%param['id']
      sys.exit()
  
  
  # take the files from first parameters
  directory = params[0]['tdir']
  tfiles = glob.glob(os.path.join(directory,"*"))      
  tfiles.sort()
    
  # construct files list
  files = []
  for tfile in tfiles:
    filename = os.path.basename(tfile[:-6])
    file = os.path.join(opt.directory,filename)
  
    if not os.path.exists(file):
      print "%s does not exists"%file 
      sys.exit()
    files.append(file)
 
 
  # check that all files have a correspondant in tdir
  for param in params:
    tfiles = glob.glob(os.path.join(directory,"*"))      
    tfiles.sort()
    
    for tfile in tfiles:
      filename = os.path.basename(tfile[:-6])
      file = os.path.join(opt.directory,filename)
      if not os.path.exists(file):
        print "%s (in param %d) does not exists"%(param['id'],file) 
        sys.exit()    
      

###################################################################################
###################################################################################
##
## main loop over all files
##
###################################################################################
###################################################################################

ifile = -1
itfile= -1

# loop over all files
for file in files:
  ifile = ifile + 1 
  itfile= itfile + 1
  # loop over all sub-frames
  for param in params:
    
    # loop over all components  
    for component in param['components']:
      
      
      if component[0] == '&':
	extcomponent = True
	
	rendering = string.split(component,"&")[1]
	fname     = string.split(component,"&")[2]
	
        print "reading ",fname,param['id'],component
        nb = Nbody(fname,ftype=param['ftype'],pio=opt.pio)	
	component = os.path.basename(fname)
      else:
	extcomponent = False
        print "reading ",file,param['id'],component
        nb = Nbody(file,ftype=param['ftype'],pio=opt.pio)
      
      
      if not extcomponent:
      
        oldparam =  param
	
	newparam=None
	##########################
	# compute param from pfile
	##########################

	if param['pfile'] != None:
	  if not os.path.isfile(param['pfile']):
	    print "parameter file %s does not exists(1)..."%(param['pfile'])
	    sys.exit()
	  
	  newparam = ReadNbodyParameters(param['pfile'])
  
	##########################
	# compute param from tdir
	##########################     
	
	if param['tdir'] != None:
	  # find the right filename
	  tfile = os.path.join(param['tdir'],os.path.basename(file))
	  tfile = "%s.%05d"%(tfile,itfile)
	  
	  if not os.path.isfile(tfile):
	    itfile = 0
	    tfile = os.path.join(param['tdir'],os.path.basename(file))
	    tfile = "%s.%05d"%(tfile,itfile)
	    if not os.path.isfile(tfile):
	      print "parameter file %s does not exists(2)..."%(tfile)
	      sys.exit()
	    
	  newparam = ReadNbodyParameters(tfile)
  
	# add usefull but values not incuded in Nbody parameters
	if newparam!=None:
	  
	  newparam['id']          = param['id']  
	  newparam['pfile']       = param['pfile']
	  newparam['tdir']        = param['tdir']	
	  newparam['components']  = param['components']
      
	  newparam['ftype']       = param['ftype']     
	  newparam['time']        = param['time']      
      
	  newparam['exec']        = param['exec']      
	  newparam['macro']       = param['macro']     
	  newparam['select']      = param['select'] 
	  
	  newparam['rendering']   = param['rendering']
	  
	  
	  # replace
	  param = newparam
		  
	

	  
      # use old params
      param['frsp'] = oldparam['frsp']
      param['filter_name'] = oldparam['filter_name']
      param['filter_opts'] = oldparam['filter_opts']
      
      ##########################
      # apply all parameters
      ##########################         

      # select component
      if not extcomponent:
        nb = nb.select(component)
      else:	
        param['rendering']=rendering

      # set shape    
      if opt.shape==None:
        param['shape'] = (width,height)
      else:
        exec("param['shape'] = %s"%(opt.shape))
	
      # set time                  
      exec("nb.tnow = %s"%param['time'])   
                                  
      # exec
      if param['exec'] != None:
        exec(param['exec']) 

      # macro
      if param['macro'] != None:
        execfile(param['macro']) 

      # select
      if param['select'] != None:
        nb = nb.select(param['select'])
            
      # compute map
      if opt.mkfits:
        mat = nb.CombiMap(param)         
      
    
      # save output
      output = '%04d_%04d-%s.fits'%(ifile,param['id'],component)
      output = os.path.join(opt.fitsdir,output)
      
  
      if os.path.exists(output):
        os.remove(output)

      header = [('TIME',nb.tnow,'snapshot time')]		     
      io.WriteFits(transpose(mat), output, extraHeader = header)	  
       


















