=begin
= netcdf_cutter.rb
== $B35MW(B
:ORG_data $B$K3JG<$5$l$k(B ERA-40 $B%*%j%8%J%k%G!<%?$r(B 1 $B%u7nKh$KJ,3d$9$k%9%/%j%W%H(B.

== USAGE
  $ netcdf_cutter.rb $B%U%!%$%kL>(B $BJQ?t(B

$B8=;~E@$G$O0J2<$N$h$&$JFqE@$,$"$k(B.

* global attribute $B$,>CLG$7$F$7$^$&(B. 
=end

#############  $B0J2<%a%$%s%k!<%A%s(B  ##############
require "numru/netcdf"


module NumRu
  class NetCDFVar
    alias put scaled_put
    alias get scaled_get
  end
end

require "numru/ggraph"
include NumRu

require "getopts"

#======= ruby 1.6 $B$G(B Date::parse $B$r$D$+$&$?$a$N$*$^$8$J$$(B
class Hash
  alias values_at indices # values_at $B$O(B ruby-1.6 $B$K$OL5$$%a%=%C%I$J$N$G(B
end
#=======

# $B0z?t$KM?$($?(B nc $B%U%!%$%k$r3JG<$9$k(B $BG[Ns(B.
file = Array.new

# $B0z?tCf$N(B nc $B%U%!%$%k$N$_3JG<(B
ARGV.each do |i| 
  if i =~ /.nc$/ then
    p i
    file << i
  end
end

# $BJQ?t(B : $B%G%U%)%k%H$O%X%C%@(B $B$N0lHV:G8e$NJQ?t$r<+F0E*$KA*Br(B
if ARGV[ARGV.size-1] =~ /.nc$/ then
  var = NetCDF.open(file[0], "r").var_names[-1]  
else # $BM[$K;XDj$b2DG=(B. $B$=$N>l9g(B, $B0lHV:G8e$KM?$($k(B.
  var = ARGV[ARGV.size-1]
end

pname = var.to_s.upcase #=> $BJ*M}NL$r(B get.

#--------------------------------------
# title $B$rF@$k(B. $B$b$7$J$1$l$P(B, longname $B$r$=$l$H$9$k(B.
nc = NetCDF.open(file[0])
p  longname = nc.var(var).att("long_name").get
p  title = nc.att("title")
nc.close

if title 
p  $title = title
else 
p  $title = "daily "+longname
end

#  gphys $B%*!<%W%s(B
#
gphys = GPhys::NetCDF_IO.open(file[0], var)

#--------------------------------------
# ECMWF $B%G!<%?$+$i@8@.$7$?(B gphys $B%*%V%8%'%/%H$N3+;OF|;~$rF|IU%*%V%8%'%/%H$K3JG<$9$k%a%=%C%I(B.
def get_start_date(gphys) 
  start_org = gphys.coord(gphys.axnames.index("date")).get_att('units')
  start = start_org[/(\d)+-(\d)+-(\d)+/]            # "2000-01-12" $B$H$+(B "99-1-3" $B$G;XDj$5$l$kItJ,$rJV$9(B
  startd = Date.parse(start)
  return startd
end
# $B%a%=%C%I%F%9%H(B
# p sd = get_start_date(gphys).to_s
#-------------------------------------

#------ function::get_mdays -------
# $B0z?t$KM?$($?F|IU%*%V%8%'%/%H$NG/$N3F7n$NF|?t$rJV$9(B
#----------------------------------
def get_mdays(d)
  mdays = Array.new
  1.upto(12){|i|
    if i == 12 then 
      date = Date.new(d.year, 12, 31) 
      mdays << date.yday - (date << 1).yday
    else 
      fdate = Date.new(d.year, i) #forward_month_date
      adate = Date.new(d.year, i+1) #after_month_date
      mdays << adate.yday - fdate.yday
    end
  }
  return mdays
end
#$B%a%=%C%I%F%9%H(B
# test = Date.new(2004)
#p get_mdays(test)
#--------------------------------------


#------ function::get_sum_mdays -------
# $B0z?t$KM?$($?F|IU%*%V%8%'%/%H$NG/$N3F7n$NN_@QF|?t(B
#--------------------------------------
def get_sum_mdays(d)
  ydays = Array.new
  1.upto(12){|i|
    date = Date.new(d.year, i)
    ydays << date.yday
  }
  return ydays
end
#$B%a%=%C%I%F%9%H(B
#  test = Date.new(2004)
# p ydays = get_sum_mdays(test)
#----------------------------------

#------ function::get_drange -------
# $B0z?t$KM?$($?F|IU%*%V%8%'%/%H$NG/$N3F7n$NN_@QF|?t(B
#--------------------------------------
def get_drange(gphys, sd)
  mdays = get_mdays(sd) # [31, 28, 31, 30, ..., 31]
  sumd = get_sum_mdays(sd) # 1, 32, 
  na_sumd = NArray.to_na(sumd) + NArray.to_na(mdays) -2
end

#------------- main ------------------

# $B%*%W%7%g%s2r@O(B ----------------------------------------------------
unless getopts("hH", "month:")
  print "#{$0}:illegal options. please exec this program with -h/--help. \n"
  exit 1
end


p a = Time.now # $B=hM}$K$+$+$C$?;~4V$r7WB,$9$k$?$a$NI[@P(B.

p sd = get_start_date(gphys)
p ad = get_drange(gphys, sd)
ydays = NArray.sint(365).indgen!

# $B@_DjItJ,(B
## RUBYLIB $B$KDI2C(B
$: << '/GFD_Dennou_Club/dc-arch/dcchart/daktu32/ERA40'
$: << '/GFD_Dennou_Club/dc-arch/dcchart/daktu32/ERA40/bin'
$: << '/work31/daktu32/ERA40'
$: << '/work31/daktu32/ERA40/bin'
## $BDI2C%a%=%C%IDj5A%U%!%$%k(B
require "libgphys-e.rb"
## $BB0@-@_Dj%U%!%$%k(B
require "ERA40-ncattr.conf.rb"

var_attr= {"units"=>"days since 2001-1-1"}

num_month = 5
num_month = ($OPT_month).to_i if ($OPT_month)

if num_month == 12 then
  sd.month.upto(sd.month + num_month-1){|i|
    if i == 1 then
      output = "daily_#{pname}_2001-0#{i}_ERA40.nc"
      p "now making "+output
      gphys.cut('date'=>0..ad[0]).save(output, $global_attr, nil, nil, $history)
      p "done"
    elsif (i < 10) then
      output = "daily_#{pname}_2001-0#{i}_ERA40.nc"
      p "now making "+output
      gphys.cut('date'=>ad[i-2]+1..ad[i-1]).save(output, $global_attr, nil, nil, $history)
      p "done"

    else 
      output = "daily_#{pname}_2001-#{i}_ERA40.nc"
      p "now making "+output
      gphys.cut('date'=>ad[i-2]+1..ad[i-1]).save(output, $global_attr, nil, nil, $history)
      p "done"
    end
  }    
else
  sd.month.upto(sd.month + num_month-1){|i|
    if i == 1 then
      output = "daily_#{pname}_2001-0#{i}_ERA40.nc"
      p "now making "+output
      gphys.cut('date'=>0..ad[0]).save(output, $global_attr, nil, nil, $history)
      p "done"
    elsif i < 7 then
      output = "daily_#{pname}_2001-0#{i}_ERA40.nc"
      p "now making "+output
      gphys.cut('date'=>ad[i-2]+1..ad[i-1]).save(output, $global_attr, nil, nil, $history)
      p "done"
    elsif (i >= 7) & (i < 10) then
      output = "daily_#{pname}_2001-0#{i}_ERA40.nc"
      p "now making "+output
      index = gphys.axnames.index("date")
      newgphys = gphys.cut('date'=>ad[i-2]-ad[5]..ad[i-1]-ad[5]-1)
      newgphys.save(output, $global_attr, "date", var_attr, $history)
      
      ng = NetCDF.open(output, "a")
      ng.var("date").put(ydays[ad[i-2]+1..ad[i-1]])
      ng.close
      
      p "done"
    else 
      output = "daily_#{pname}_2001-#{i}_ERA40.nc"
      p "now making "+output
      index = gphys.axnames.index("date")
      newgphys = gphys.cut('date'=>ad[i-2]-ad[5]..ad[i-1]-ad[5]-1)
      newgphys.save(output, $global_attr, "date", var_attr, $history)
      
      ng = NetCDF.open(output, "a")
      ng.var("date").put(ydays[ad[i-2]+1..ad[i-1]])
      ng.close
      
    end
  }
end

p Time.now - a
