/*
 * access to parameters of ETA coordinate
 *
 * subc_eta(type1, type2, type3, basetime, member, validtime, "get")
 *  arguments:
 *   type1, type2, type3, member: String
 *   basetime, validtime: Integer (minuits from 00:00 1 Jan 1801)
 *  return:
 *   n_levels: Integer (number of levels)
 *   a, b: NArray[n_levels+1]
 *   c: Float
 *
 * subc_eta(type1, type2, type3, basetime, member, validtime, "put", a, b, c)
 *  arguments:
 *   type1, type2, type3, member: String
 *   basetime, validtime: Integer (minuits from 00:00 1 Jan 1801)
 *   a, b: NArray[n_levels+1] || Array[n_levels+1]
 *   c: Float
 *  return:
 *   nil
 */
VALUE
rb_subc_eta(int argc, VALUE *argv, VALUE self)
{
  VALUE type1, type2, type3;
  VALUE basetime, member, validtime;
  VALUE getput;
  VALUE a, b, c;
  VALUE obj;

  N_SI4 cn_levels;
  float *ca=NULL, *cb=NULL, cc;

  VALUE* ary;
  struct NARRAY* nary;
  float *cary;
  N_SI4 code;
  int flag=-1;

  int i;

  rb_scan_args(argc, argv, "73",
               &type1, &type2, &type3,
               &basetime, &member, &validtime,
               &getput,
               &a, &b, &c);

  GetTypes;
  GetTimesAndMember;

  GetChar(getput,3);

  if (strcmp(cgetput,"get") || strcmp(cgetput,"GET")) {
    if (argc != 7)
      rb_raise(rb_eArgError, "wrong number of arguments for get (%d for 7)", argc);
    code = nusdas_subc_eta_inq_nz(ctype1, ctype2, ctype3,
                                  &cbasetime, cmember, &cvalidtime,
                                  "ETA ", &cn_levels);
    if (code <= 0)
      rb_raise(rb_eRuntimeError, "faild: nusdas_subc_eta_inq_nz, code=%d", code);
    ca = xmalloc( sizeof(float)*(cn_levels+1) );
    cb = xmalloc( sizeof(float)*(cn_levels+1) );
    flag = 1;
  } else if (strcmp(cgetput,"put") || strcmp(cgetput,"PUT")) {
    if (argc != 10)
      rb_raise(rb_eArgError, "wrong number of arguments for put (%d for 11)", argc);

    if (TYPE(a)==T_ARRAY) {
      cn_levels = RARRAY_LEN(a)-1;
      ca = xmalloc( sizeof(float)*(cn_levels+1) );
      ary = RARRAY_PTR(a);
      for (i=0;i<cn_levels+1;i++)
        ca[i] = (float)NUM2DBL(ary[i]);
    } else if (IsNArray(a)){
      cn_levels = NA_TOTAL(a);
      ca = xmalloc( sizeof(float)*(cn_levels+1) );
      b = na_cast_object(b, NA_SFLOAT);
      GetNArray(b,nary);
      cary = NA_PTR_TYPE(nary,float*);
      for (i=0;i<cn_levels+1;i++)
        ca[i] = cary[i];
    } else
      rb_raise(rb_eArgError, "a must be NArray of Array");

    if (TYPE(b)==T_ARRAY) {
      if (RARRAY_LEN(b)!=cn_levels+1)
        rb_raise(rb_eArgError, "length of b must be the same as a");
      cb = xmalloc( sizeof(float)*(cn_levels+1) );
      ary = RARRAY_PTR(b);
      for (i=0;i<cn_levels+1;i++)
        cb[i] = (float)NUM2DBL(ary[i]);
    } else if (IsNArray(b)){
      if (NA_TOTAL(b)!=cn_levels+1)
        rb_raise(rb_eArgError, "length of b must be the same as a");
      cb = xmalloc( sizeof(float)*(cn_levels+1) );
      b = na_cast_object(b, NA_SFLOAT);
      GetNArray(b,nary);
      cary = NA_PTR_TYPE(nary,float*);
      for (i=0;i<cn_levels+1;i++)
        cb[i] = cary[i];
    } else
      rb_raise(rb_eArgError, "b must be NArray of Array");

    cc = NUM2DBL(c);
    flag = 2;
  }

  nusdas_subc_eta(ctype1, ctype2, ctype3,
                  &cbasetime, cmember, &cvalidtime,
                  &cn_levels, ca, cb, &cc,
                  cgetput);

  switch (flag) {
  case 1:
    a = rb_ary_new();
    b = rb_ary_new();
    for (i=0;i<cn_levels+1;i++) {
      rb_ary_push(a, rb_float_new((double)ca[i]) );
      rb_ary_push(b, rb_float_new((double)cb[i]) );
    }
    obj = rb_ary_new();
    rb_ary_push(obj, INT2NUM((int)cn_levels));
    rb_ary_push(obj, a);
    rb_ary_push(obj, b);
    rb_ary_push(obj, rb_float_new((double)cc) );
    break;
  case 2:
    obj = Qnil;
    break;
  default:
    rb_raise(rb_eRuntimeError, "failed");
    exit(-1);
  }

  free(ca);
  free(cb);
  return obj;
}