/** \file
 * \brief IM Lua 5 Binding
 *
 * See Copyright Notice in im_lib.h
 */

#include <memory.h>

#include "im.h"
#include "im_image.h"
#include "im_process.h"
#include "im_util.h"

#include <lua.h>
#include <lauxlib.h>

#include "imlua.h"
#include "imlua_aux.h"
#include "imlua_image.h"


#define imlua_checkcomplex(_L, _a, _i) \
  luaL_argcheck(L, ((_i)->data_type == IM_CFLOAT || (_i)->data_type == IM_CDOUBLE), _a, "image data type can be complex only");


/*****************************************************************************\
 Domain Transform Operations
\*****************************************************************************/

/*****************************************************************************\
 im.ProcessFFT(src_image, dst_image)
\*****************************************************************************/
static int imluaProcessFFT (lua_State *L)
{
  imImage* src_image = imlua_checkimage(L, 1);
  imImage* dst_image = imlua_checkimage(L, 2);

  imlua_matchsize(L, src_image, dst_image);
  imlua_checkcomplex(L, 2, dst_image);

  imProcessFFT(src_image, dst_image);
  return 0;
}

/*****************************************************************************\
 im.ProcessIFFT(src_image, dst_image)
\*****************************************************************************/
static int imluaProcessIFFT (lua_State *L)
{
  imImage* src_image = imlua_checkimage(L, 1);
  imImage* dst_image = imlua_checkimage(L, 2);

  imlua_matchsize(L, src_image, dst_image);
  imlua_checkcomplex(L, 1, src_image);
  imlua_checkcomplex(L, 2, dst_image);

  imProcessIFFT(src_image, dst_image);
  return 0;
}

/*****************************************************************************\
 im.ProcessFFTRaw(src_image, inverse, center, normalize)
\*****************************************************************************/
static int imluaProcessFFTraw (lua_State *L)
{
  imImage* src_image = imlua_checkimage(L, 1);
  int inverse = (int)luaL_checkinteger(L, 2);
  int center = (int)luaL_checkinteger(L, 3);
  int normalize = (int)luaL_checkinteger(L, 4);

  imlua_checkcomplex(L, 1, src_image);

  imProcessFFTraw(src_image, inverse, center, normalize);
  return 0;
}

/*****************************************************************************\
 im.ProcessSwapQuadrants(src_image, inverse, center, normalize)
\*****************************************************************************/
static int imluaProcessSwapQuadrants (lua_State *L)
{
  imImage* src_image = imlua_checkimage(L, 1);
  int center2origin = (int)luaL_checkinteger(L, 2);

  imlua_checkcomplex(L, 1, src_image);

  imProcessSwapQuadrants(src_image, center2origin);
  return 0;
}

/*****************************************************************************\
 im.ProcessCrossCorrelation(image1, image2, dst_image)
\*****************************************************************************/
static int imluaProcessCrossCorrelation (lua_State *L)
{
  imImage* image1 = imlua_checkimage(L, 1);
  imImage* image2 = imlua_checkimage(L, 2);
  imImage* dst_image = imlua_checkimage(L, 3);

  imlua_matchsize(L, image1, dst_image);
  imlua_matchsize(L, image2, dst_image);
  imlua_checkcomplex(L, 3, dst_image);

  imProcessCrossCorrelation(image1, image2, dst_image);
  return 0;
}

/*****************************************************************************\
 im.ProcessAutoCorrelation(src_image, dst_image)
\*****************************************************************************/
static int imluaProcessAutoCorrelation (lua_State *L)
{
  imImage* src_image = imlua_checkimage(L, 1);
  imImage* dst_image = imlua_checkimage(L, 2);

  imlua_matchsize(L, src_image, dst_image);
  imlua_checkcomplex(L, 2, dst_image);

  imProcessAutoCorrelation(src_image, dst_image);
  return 0;
}

static const luaL_Reg imfftw_lib[] = {
  {"ProcessFFT", imluaProcessFFT},
  {"ProcessIFFT", imluaProcessIFFT},
  {"ProcessFFTraw", imluaProcessFFTraw},
  {"ProcessSwapQuadrants", imluaProcessSwapQuadrants},
  {"ProcessCrossCorrelation", imluaProcessCrossCorrelation},
  {"ProcessAutoCorrelation", imluaProcessAutoCorrelation},

  {NULL, NULL}
};

int imlua_open_fftw (lua_State *L)
{
  imlua_register_lib(L, imfftw_lib);  /* leave im table at the top of the stack */

#ifdef IMLUA_USELOH
#include "im_fftw.loh"
#else
#ifdef IMLUA_USELH
#include "im_fftw.lh"
#else
  luaL_dofile(L, "im_fftw.lua");
#endif
#endif

  return 1;
}

int luaopen_imlua_fftw(lua_State *L)
{
  return imlua_open_fftw(L);
}
