#!/usr/bin/env ruby

require "getopts"
require "numru/ggraph"

include NumRu


module NumRu
  class NetCDFVar

    def get_with_miss_and_scaling_new(*args) # make mask before scaling
p 11111111111111111
      __interpret_missing_params if !defined?(@missval)
      packed_data = simple_get(*args)
      scaled_data = scaled_get(*args)
      if @vmin || @vmax
	if @vmin
	  mask = (packed_data >= @vmin) 
	  mask = mask.and(packed_data <= @vmax) if @vmax
	else
	  mask = (packed_data <= @vmax)
	end
	data = NArrayMiss.to_nam(scaled_data, mask)
      elsif @missval	# only missing_value is present.
	eps = 1e-6
      missval = @missval[0].to_f
	vmin = missval - eps
      vmax = missval + eps
	mask = (packed_data <= vmin) 
	mask = mask.or(packed_data >= vmax)
	data = NArrayMiss.to_nam(scaled_data, mask)
      else
	data = scaled_data
      end
      data
    end
    
    def put_with_miss_and_scaling_new(data, *args)
p 222222222222222
      if data.is_a?( NArrayMiss )
	__interpret_missing_params if !defined?(@missval)
	if @missval
	scaled_put_without_missval(data, *args)
	else
	  scaled_put(data.to_na, *args)
	end
      else
	scaled_put(data, *args)
      end
    end
    
    def scaled_put_without_missval(var,hash=nil)
      sf = att('scale_factor')
      ao = att('add_offset')
      if ( sf == nil && ao == nil ) then
	# no scaling --> just call put
      simple_put(var,hash)
      else
	if (sf != nil) 
	  csf = sf.get
	  if csf.is_a?(NArray) then  # --> should be a numeric
	    csf = csf[0]
	  elsif csf.is_a?(String)
	  raise TypeError, "scale_factor is not a numeric"
	  end
	  if(csf == 0) then; raise NetcdfError, "zero scale_factor"; end
	else
	  csf = 1.0      # assume 1 if not defined
	end
	if (ao != nil) 
	  cao = ao.get
	  if cao.is_a?(NArray) then  # --> should be a numeric
	    cao = cao[0]
	  elsif csf.is_a?(String)
	    raise NetcdfError, "add_offset is not a numeric"
	  end
	else
	  cao = 0.0      # assume 0 if not defined
	end
	var = var.to_na( @missval[0]*csf + cao)
	simple_put( (var-cao)/csf, hash )
      end
    end  
    
    # NetCDF_Conventions 中で hoge_with_miss_and_scaling を alias しているがための処置  
    alias get get_with_miss_and_scaling_new
    alias put put_with_miss_and_scaling_new
  end
end


def gtadd(file)
  gphys_file = Array.new
  
  file.each {|f|  
    var = NetCDF.open(f, "r").var_names[-1]
    temp = GPhys::NetCDF_IO.open(f, var)
    gphys_file << temp
  }
  
  sum = gphys_file[0]
  
  1.upto(gphys_file.size-1) do |i|
    sum += gphys_file[i]
  end
  
  gphys = sum

  return gphys
end


# オプション解析 ----------------------------------------------------

unless getopts("hH", "help", "o:", "output:")
  print "#{$0}:illegal options. please exec this program with -h/--help. \n"
  exit 1
end


# 保存ファイル名が与えられたら, その名前で保存. デフォルトは "gtadd.nc".
if ($OPT_o) then
  output = ($OPT_o).to_s
elsif ($OPT_output) then
  output = ($OPT_output).to_s
else 
  output = "gtadd-n.nc"
end


# オプション解析 終了----------------------------------------------------



# メインルーチン

files = ARGV#.delete_if{|x| x !=~ /^(.*)\.nc$/}

  # 引数最初のデータの SF, AO を取得
  var = NetCDF.open(ARGV[0], "r").var_names[-1]
  gp1 = GPhys::IO.open(ARGV[0], var)
  sf = gp1.data.get_att('scale_factor') if gp1.data.get_att('scale_factor')
  ao = gp1.data.get_att('add_offset') if gp1.data.get_att('add_offset')

gphys = gtadd(files)
gphys.data.set_att('scale_factor', sf)
gphys.data.set_att('add_offset', ao)
vname = NetCDF.open(files[0], "r").var_names[-1]

  GPhys::IO.write(gphys)

  ## ヘッダを Monthly-Mean 用に書き換え ----------------------
  nc = NetCDF.open(output, mode="a+")
  nc.redef # into define mode
  # 変数属性を書き換え
  var = nc.var(var)
  var.each_att do |att|
    att_val = att.get
    if att_val.is_a?(String)
      att.put(att_val.sub(/^4x\ *[D|d]aily/, "Monthly Mean"))
    end
  end
  # 大域属性を書き換え
  nc.each_att do |att|
    att_val = att.get
    if att_val.is_a?(String)
      att.put(att_val.sub(/^4x\ *[D|d]aily/, "Monthly Mean"))
    end
  end
  nc.close

exit
