#include "Mat.h"

static int Mat__tostring(lua_State *L)
{
  Mat *p=checkMat(L,1);
  lua_pushfstring(L,MAT_NAME" object: %p\n\t"MAT_NAME" row(int y)\n\t"MAT_NAME" col(int x)\n\t"MAT_NAME" rowRange(int startrow, int endrow)\n\t"MAT_NAME" colRange(int startcol, int endcol)\n\t"MAT_NAME" diag(int d=0)\n\t"MAT_NAME" diag("MAT_NAME" d)\n\t"MAT_NAME" clone()\n\t",p);
  return 1;
}

static int Mat__gc(lua_State *L)
{
  luacv_obj<Mat>*obj=(luacv_obj<Mat>*)luaL_checkudata(L,1,MAT_NAME);
  if (obj->dealloc_data)
    delete obj->data;
  return 0;
}

static int Mat_row(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.row(int y)";
  if(lua_gettop(L)!=2) luaL_error(L,f_msg);
  Mat p=checkMat(L,1)->row(checkint(L,2));
  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}

static int Mat_col(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.col(int y)";
  if(lua_gettop(L)!=2) luaL_error(L,f_msg);

  Mat p=checkMat(L,1)->col(checkint(L,2));
  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}

static int Mat_rowRange(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.rowRange(int startrow, int endrow)";
  if(lua_gettop(L)!=3) luaL_error(L,f_msg);

  Mat p=checkMat(L,1)->rowRange(checkint(L,2),checkint(L,3));
  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}
static int Mat_colRange(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.colRange(int startcol, int endcol)";
  if(lua_gettop(L)!=3) luaL_error(L,f_msg);

  Mat p=checkMat(L,1)->colRange(checkint(L,2),checkint(L,3));
  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}
static int Mat_diag(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.diag(int d=0) || "MAT_NAME" Mat.diag("MAT_NAME" d)";
  int top=lua_gettop(L);
  Mat p;
  switch(top)
  {
    case 1: 
             p=checkMat(L,1)->diag();
            break;
    case 2:
            if (lua_isuserdata(L,2))
              p=checkMat(L,1)->diag(*checkMat(L,2));
            else
              p=checkMat(L,1)->diag(checkint(L,2));
            break;
    default:
            luaL_error(L,f_msg);
  }

  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}
static int Mat_clone(lua_State *L)
{
  const char f_msg[]=MAT_NAME" Mat.clone()";
  if(lua_gettop(L)!=1) luaL_error(L,f_msg);

  Mat p=checkMat(L,1)->clone();
  pushUserData(L,&p);
  luaL_getmetatable(L,MAT_NAME);
  lua_setmetatable(L,-2);
  return 1;
}

const luaL_Reg Mat_m[]=
{
  {"__tostring",Mat__tostring},
  {"__gc",Mat__gc},
  {"row",Mat_row},
  {"col",Mat_col},
  {"rowRange",Mat_rowRange},
  {"colRange",Mat_colRange},
  {"diag",Mat_diag},
  {"clone",Mat_clone},
  {NULL,NULL}
};
