/*
 * GStreamer
 * Copyright (C) 2011 Robert Jobbagy <jobbagy.robert@gmail.com>
 * Copyright (C) 2011 Nicola Murino <nicola.murino@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Alternatively, the contents of this file may be used under the
 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
 * which case the following provisions apply instead of the ones
 * mentioned above:
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef MOTIONCELLS_H_
#define MOTIONCELLS_H_

#include <opencv2/core/core_c.h>
#ifdef HAVE_HIGHGUI_H
#include <highgui.h>            // includes highGUI definitions
#endif
#ifdef HAVE_OPENCV2_HIGHGUI_HIGHGUI_C_H
#include <opencv2/highgui/highgui_c.h>            // includes highGUI definitions
#endif
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdio>
#include <cmath>
#include <glib.h>

//MotionCells defines
#define MC_HEADER 64
#define MC_TYPE 1
#define MC_VERSION 1
#define MC_VERSIONTEXT "MotionCells-1"
#define MSGLEN 6
#define BUSMSGLEN 20

using namespace std;

struct MotionCellHeader{
	gint32 headersize;
	gint32 type;
	gint32 version;
	gint32 itemsize;
	gint32 gridx;
	gint32 gridy;
	gint64 starttime;
	char name[MC_HEADER - 32];
};

struct MotionCellData{
	gint32 timestamp;
	char *data;
};

typedef struct {
	int upper_left_x;
	int upper_left_y;
	int lower_right_x;
	int lower_right_y;
} motionmaskcoordrect;

typedef struct {
	int R_channel_value;
	int G_channel_value;
	int B_channel_value;
} cellscolor;

typedef struct {
	int lineidx;
	int columnidx;
} motioncellidx;

struct Cell
{
  double MotionArea;
  double CellArea;
  double MotionPercent;
  bool hasMotion;
};

struct MotionCellsIdx
{
  CvRect motioncell;
  //Points for the edges of the rectangle.
  CvPoint cell_pt1;
  CvPoint cell_pt2;
  int lineidx;
  int colidx;
};

struct OverlayRegions
{
  CvPoint upperleft;
  CvPoint lowerright;
};

class MotionCells
{
public:

  MotionCells ();
  virtual ~ MotionCells ();

  int performDetectionMotionCells (IplImage * p_frame, double p_sensitivity,
      double p_framerate, int p_gridx, int p_gridy, gint64 timestamp_millisec,
      bool p_isVisble, bool p_useAlpha, int motionmaskcoord_count,
      motionmaskcoordrect * motionmaskcoords, int motionmaskcells_count,
      motioncellidx * motionmaskcellsidx, cellscolor motioncellscolor,
      int motioncells_count, motioncellidx * motioncellsidx, gint64 starttime,
      char *datafile, bool p_changed_datafile, int p_thickness);

  void setPrevFrame (IplImage * p_prevframe)
  {
    m_pprevFrame = cvCloneImage (p_prevframe);
  }
  char *getMotionCellsIdx ()
  {
    return m_motioncellsidxcstr;
  }

  int getMotionCellsIdxCount ()
  {
    return m_motioncells_idx_count;
  }

  bool getChangedDataFile ()
  {
    return m_changed_datafile;
  }

  char *getDatafileInitFailed ()
  {
    return m_initdatafilefailed;
  }

  char *getDatafileSaveFailed ()
  {
    return m_savedatafilefailed;
  }

  int getInitErrorCode ()
  {
    return m_initerrorcode;
  }

  int getSaveErrorCode ()
  {
    return m_saveerrorcode;
  }

  void freeDataFile ()
  {
    if (mc_savefile) {
      fclose (mc_savefile);
      mc_savefile = NULL;
      m_saveInDatafile = false;
    }
  }

private:

  double calculateMotionPercentInCell (int p_row, int p_col, double *p_cellarea,
      double *p_motionarea);
  void performMotionMaskCoords (motionmaskcoordrect * p_motionmaskcoords,
      int p_motionmaskcoords_count);
  void performMotionMask (motioncellidx * p_motionmaskcellsidx,
      int p_motionmaskcells_count);
  void calculateMotionPercentInMotionCells (motioncellidx *
      p_motionmaskcellsidx, int p_motionmaskcells_count = 0);
  int saveMotionCells (gint64 timestamp_millisec);
  int initDataFile (char *p_datafile, gint64 starttime);
  void blendImages (IplImage * p_actFrame, IplImage * p_cellsFrame,
      float p_alpha, float p_beta);

  void setData (IplImage * img, int lin, int col, uchar valor)
  {
    ((uchar *) (img->imageData + img->widthStep * lin))[col] = valor;
  }

  uchar getData (IplImage * img, int lin, int col)
  {
    return ((uchar *) (img->imageData + img->widthStep * lin))[col];
  }

  bool getIsNonZero (IplImage * img)
  {
    for (int lin = 0; lin < img->height; lin++)
      for (int col = 0; col < img->width; col++) {
        if ((((uchar *) (img->imageData + img->widthStep * lin))[col]) > 0)
          return true;
      }
    return false;
  }

  void setMotionCells (int p_frameWidth, int p_frameHeight)
  {
    m_cellwidth = (double) p_frameWidth / (double) m_gridx;
    m_cellheight = (double) p_frameHeight / (double) m_gridy;
    m_pCells = new Cell *[m_gridy];
    for (int i = 0; i < m_gridy; i++)
      m_pCells[i] = new Cell[m_gridx];

    //init cells
    for (int i = 0; i < m_gridy; i++)
      for (int j = 0; j < m_gridx; j++) {
        m_pCells[i][j].MotionArea = 0;
        m_pCells[i][j].CellArea = 0;
        m_pCells[i][j].MotionPercent = 0;
        m_pCells[i][j].hasMotion = false;
      }
  }

  IplImage *m_pcurFrame, *m_pprevFrame, *m_pdifferenceImage,
      *m_pbwImage,*transparencyimg;
  CvSize m_frameSize;
  bool m_isVisible, m_changed_datafile, m_useAlpha, m_saveInDatafile;
  Cell **m_pCells;
  vector < MotionCellsIdx > m_MotionCells;
  vector < OverlayRegions > m_OverlayRegions;
  int m_gridx, m_gridy;
  double m_cellwidth, m_cellheight;
  double m_alpha, m_beta;
  double m_sensitivity;
  int m_framecnt, m_motioncells_idx_count, m_initerrorcode, m_saveerrorcode;
  char *m_motioncellsidxcstr, *m_initdatafilefailed, *m_savedatafilefailed;
  FILE *mc_savefile;
  MotionCellHeader m_header;

};

#endif /* MOTIONCELLS_H_ */
