# include "data.h"

int shift (int argc, char **argv) {
 
  int i, j, N, ROLL;
  int nx, ny, dx, dy, DXin, DXot, DYin, DYot;
  float *Vin, *Vot;
  double Dx, Dy, fdx, fdy;
  Buffer *buf;

  ROLL = FALSE;
  if (N = get_argument (argc, argv, "-roll")) {
    remove_argument (N, &argc, argv);
    ROLL = TRUE;
  }

  if (argc != 4) {
    fprintf (stderr, "USAGE: shift <buffer> dx dy\n");
    return (FALSE);
  }

  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);

  Dx = -atof (argv[2]);
  Dy = -atof (argv[3]);

  dx = Dx;
  dy = Dy;
  fdx = Dx - dx;
  fdy = Dy - dy;
  if (fdx < -0.001) {dx -= 1; fdx += 1;}
  if (fdy < -0.001) {dy -= 1; fdy += 1;}

  nx = buf[0].matrix.Naxis[0];
  ny = buf[0].matrix.Naxis[1];

  if ((dx > buf[0].matrix.Naxis[0]) || (dy > buf[0].matrix.Naxis[1])) {
    fprintf (stderr, "shifting data out of image\n");
    return (FALSE);
  }
  
  if (dx < 0) {
    DXin = 0;
    DXot = -dx;
  } else {
    DXin = dx;
    DXot = 0;
  }
  if (dy < 0) {
    DYin = 0;
    DYot = -dy;
  } else {
    DYin = dy;
    DYot = 0;
  }
  
  if ((dy > 0) || ((dy == 0) && (dx > 0))) {
    for (j = 0; j < ny - fabs(dy); j++) {
      Vin = (float *)(buf[0].matrix.buffer) + (j + DYin)*nx + DXin;  
      Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx + DXot; 
      for (i = 0; i < nx - fabs(dx); i++, Vin++, Vot++) {
	*Vot = *Vin;
      }
      if (dx < 0) 
	Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx; 
      for (i = 0; i < fabs(dx); i++, Vot++) {
	*Vot = 0.0;
      }	
    }
    Vot = (float *)(buf[0].matrix.buffer) + nx*(ny - abs(dy));
    for (j = 0; j < nx * fabs(dy); j++, Vot++) {
      *Vot = 0.0;
    }   
  } else {
    for (j = ny - fabs(dy) - 1; j >= 0; j--) {
      Vin = (float *)(buf[0].matrix.buffer) + (j + DYin)*nx + DXin + nx - abs(dx) - 1; 
      Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx + DXot + nx - abs(dx) - 1; 
      for (i = 0; i < nx - fabs(dx); i++, Vin--, Vot--) {
	*Vot = *Vin;
      }
      if (dx < 0) 
	Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx; 
      for (i = 0; i < fabs(dx); i++, Vot++) {
	*Vot = 0.0;
      }	
    }
    Vot = (float *)(buf[0].matrix.buffer);
    for (j = 0; j < nx * fabs(dy); j++, Vot++) {
      *Vot = 0.0;
    }
  } 

  fprintf (stderr, "%f %f\n", fdx, fdy);
  if ((fdx > 0) || (fdy > 0)) {
    double f00, f01, f10, f11;
    float value;

    f00 = (1-fdx)*(1-fdy);
    f01 =    fdx *(1-fdy);
    f10 = (1-fdx)*   fdy;
    f11 =    fdx *   fdy;

    Vin = (float *)buf[0].matrix.buffer;
    Vot = (float *)buf[0].matrix.buffer;
    for (j = 0; j < ny - 1; j++) {
      for (i = 0; i < nx - 1; i++, Vin++, Vot++) {
	value  = Vin[   0] * f00;
	value += Vin[   1] * f01;
	value += Vin[ny  ] * f10;
	value += Vin[ny+1] * f11;
	*Vot = value;
      }
      Vin ++;
      Vot ++;
    }
  }   

  return (TRUE);

}

