#!/usr/bin/env ruby

require "getopts"        # for option_parse
require "numru/netcdf"

class NArray # for deep_copy
  def self._load(o); to_na(*Marshal::load(o)).ntoh; end
  def _dump(limit); Marshal::dump([hton.to_s, typecode, *shape]); end
end

module NumRu
  class NetCDFVar
    def scaled_get(hash=nil)
      sf = att('scale_factor')
      ao = att('add_offset')
      if ( sf == nil && ao == nil ) then
	# no scaling --> just call get
	simple_get(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 NetcdfError, "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 = simple_get(hash)
	var = var.to_type( NArray::FLOAT )
	csf*var+cao
      end
    end  
    alias put scaled_put
    alias get scaled_get
  end
end

require "libgphys-e" # 内部で numru/ggraph を呼び出している
require "libdraw"
include Draw


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


unless getopts("hHfnc", "help", "file", "native", "mean:", "itr:", "title:", "range:", "nocont", "noshade", "line", "map", "noannote", "animate:", "smooth:", "bs", "nowait")
  print "#{$0}:illegal options. please exec this program with -h/--help. \n"
  exit 1
end

if ($OPT_animate) && ($OPT_smooth)
  print "please set options only animate or smooth\n"
  exit 1
end

file = Array.new         # 引数中の nc ファイルを配列に格納
ARGV.each do |i|         
  if i =~ /.nc$/ then
    p i
    file << i
  end
end

if ARGV[ARGV.size-1] =~ /.nc$/ then
  var = NetCDF.open(file[0], "r").var_names[-1]
else 
  var = ARGV[ARGV.size-1]
end


p var

if file.size == 1 then # 単一ファイルが指定された場合
  gphys = GPhys::NetCDF_IO.open(file[0].to_s, var)
 p  $title = File::basename(file[0].to_s, ".nc")
else 
  if ($OPT_c)          # コンポジット. 引数に与えられたファイルが領域分割されたファイルの場合, それらを仮想的に"くっつけて扱う."
    gphys = GPhys::NetCDF_IO.open(file, var)
  else
    gphys = mean_gphys(file, var)
  end
end


if ($OPT_range)
  range = ($OPT_range).to_s.split(/\s*,\s*/)
  range.each{|rg|
    ran = rg.to_s.split(/\s*=\s*/)
    if ran[1] =~ /\s*\.\.\s*/
      rg1=ran[1].split(/\s*\.\.\s*/)[0].to_f
      rg2=ran[1].split(/\s*\.\.\s*/)[1].to_f
      gphys = gphys.cut(ran[0] => rg1..rg2)
    else
      gphys = gphys.cut(ran[0] => ran[1].to_f)
    end
  }
end

$title = ($OPT_title) if ($OPT_title)

if ($OPT_mean)
  mean = ($OPT_mean).to_s.split(/\s*,\s*/)
  mean.each{|mn|
    gphys = gphys.mean(gphys.axnames.index(mn))
  }
end


##########################################
#
#    描画オプションの初期値

  draw_opts = {                  # default
    "levels"     => $OPT_levels,   # false
    "patterns"   => $OPT_patterns, # false
    "line"       => $OPT_line,     # false
    "cont"       => !$OPT_nocont,  # true
    "tone"       => !$OPT_noshade, # true
    "colorbar"   => !$OPT_colorbar,# true
    "colorbar_opts"   => nil,# nil
    "annot"     => !$OPT_noannote,  # true
    "map"        => $OPT_map       # false
   }


##########################################
#
#    変数毎に設定読み込み

if  var == "t" then
  Draw::settei_T
elsif var == "u" || var == "uwnd" then 
  Draw::settei_U(gphys)
elsif var == "v" then 
  Draw::settei_V(gphys)
elsif var == "w" then 
  Draw::settei_W(gphys)
elsif var == "cp" then
  Draw::settei_CP
elsif var == "tsrc" then
  Draw::settei_tsrc
elsif var == "lsp" then  
  Draw::settei_LSP
elsif var == "tp" then  
  Draw::settei_TP(draw_opts)
elsif ($OPT_native) || ($OPT_n) then
  Draw::settei_native
elsif var == "psi" then
  Draw::settei_strm(gphys)
elsif var == "theta" then
  Draw::settei_Theta
elsif var == "pbar" then
  Draw::settei_Available
elsif var == "pws" then
  Draw::settei_PWS
else
  Draw::settei_native
end

Draw_opts_main = draw_opts.clone #Marshal.load(Marshal.dump(draw_opts)).clone


##########################################
#
#    実際に描画部分

DCL.swlset('lalt', true)   if ($OPT_bs) || ($OPT_smooth)

if ($OPT_animate) || ($OPT_smooth)
  DCL.swlset('lwait', false) if ($OPT_nowait) || ($OPT_smooth) # auto animation
  DCL::swlset('lsep',true) if ($OPT_f)

  anirange = ($OPT_animate).to_s.split(/\s*,\s*/) if ($OPT_animate)
  anirange = ($OPT_smooth).to_s.split(/\s*,\s*/) if ($OPT_smooth)

  anirange.each{|rg|
    ran = rg.to_s.split(/\s*=\s*/)
    dimindex = gphys.dim_index(ran[0])
    if ran[1] =~ /\s*\.\.\s*/                    # 開始点と終点が指定された場合
#      arg1=ran[1].split(/\s*\.\.\s*/)[0].to_f       # 軸の値(緯度経度で指定するばあいのルーチン)
#      arg2=ran[1].split(/\s*\.\.\s*/)[1].to_f       #
#      grid1 = gphys.coord(dimindex).val.index(arg1) #
#      grid2 = gphys.coord(dimindex).val.index(arg2) #
      arg1 = ran[1].split(/\s*\.\.\s*/)[0].to_i      # 
      arg2 = ran[1].split(/\s*\.\.\s*/)[1].to_i      #
      val = gphys.coord(dimindex).val[ran[1].to_i]
      Draw::mkwin
      Draw::draw(gphys.cut(ran[0]=>val), true, Draw_opts_main)
      arg1+1.upto(arg2) do |i|
        val = gphys.coord(dimindex).val[i]
        Draw::draw(gphys.cut(ran[0]=>val), true, Draw_opts_main)
      end
    else                                         # 開始点のみ指定された場合
      val = gphys.coord(dimindex).val[ran[1].to_i]
      Draw::mkwin
      Draw::draw(gphys.cut(ran[0]=>val), true, Draw_opts_main)
      ept = gphys.coord(dimindex).shape_current[0].to_i
      (ran[1].to_i+1).upto(ept-1) { |i|
        val = gphys.coord(dimindex).val[i]
        Draw::draw(gphys.cut(ran[0]=>val), true, Draw_opts_main)
      }
    end
  }
else
  Draw::mkwin
  Draw::draw(gphys, true, Draw_opts_main) 
end

Draw::clwin

exit
