"""vision.py

Machine vision processing support using OpenCV."""

import os
import sys
import logging
import argparse
import datetime

# OpenCV
import cv2 as cv

# NumPy
import numpy as np

# initialize logging for this module
log = logging.getLogger('vision')

#================================================================
class VideoRegion:
    """Process a specific region within an image sequence to extract audience information.
    :param roi: list of two points representing an image rectangle
    """
    def __init__(self, roi):

        # save the ((ul_col,ul_row),(lr_col,lr_row)) bounds from the source image
        self.roi    = roi
        self.col    = self.roi[0][0]
        self.row    = self.roi[0][1]
        self.width  = roi[1][0] - roi[0][0]
        self.height = roi[1][1] - roi[0][1]

        # create a convenient name
        self.name = "region-%d-%d" % (self.col, self.row)

        # create a buffer to cache the image
        self.region = np.zeros((self.height, self.width), dtype=np.uint8)

        # create a background subtractor
        self.background_subtractor = cv.createBackgroundSubtractorMOG2()
        self.bk_initialized = False

        # create a buffer to cache the foreground mask
        self.foreground = np.zeros((self.height, self.width), dtype=np.uint8)

        # timestamp of last change of detection state
        self.motion_detected = False
        self.detection_timestamp = None

        # timestamp of last debugging capture
        self.capture_timestamp = None

        return

    #---------------------------------------------------------------
    def update(self, frame):
        """Update the region processing given a new full camera frame."""

        # create a submatrix referencing an image region
        img = frame[self.row:self.row+self.height, self.col:self.col+self.width]
        self.region[:,:] = img.reshape(self.height, self.width)

        # update the background subtraction with the new image, returning an
        # updated binary foreground mask

        if not self.bk_initialized:
            # on the first capture, reset the background using a learningRate of 1.0
            self.background_subtractor.apply(img, self.foreground, 1.0)
            self.bk_initialized = True
            return False

        else:
            # the third parameter can be a learning rate, maybe should be a
            # small positive value (e.g. 0.01) for regular frames
            self.background_subtractor.apply(img, self.foreground)

            motion = self.is_motion_detected()

            # capture the timestamp of transitions
            if motion != self.motion_detected:
                self.motion_detected = motion
                self.detection_timestamp = datetime.datetime.now()
                return True
            else:
                return False

    #---------------------------------------------------------------
    def is_motion_detected(self):
        """Process the current foreground mask to detect large changes representing motion."""

        image = self.foreground
        ret, thresholded = cv.threshold(image, 127, 255, cv.THRESH_BINARY)
        dilated = cv.dilate(thresholded, None, iterations=0)

        contours, hierarchy = cv.findContours(dilated, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        for contour in contours:
            area = cv.contourArea(contour)
            if area > 200:
                # log.debug("Found image difference area %f", area)
                self.detection_timestamp = datetime.datetime.now()
                return True

        return False

    #---------------------------------------------------------------
    def write_capture_file(self):

        now = datetime.datetime.now()
        folder = os.path.expanduser("logs")
        filename = now.strftime("%Y-%m-%d-%H-%M-%S") + "-region-%d-%d.png" % (self.col, self.row)
        path = os.path.join(folder, filename)
        cv.imwrite(path, self.region)
        log.debug("Wrote region image to %s", path)
        self.capture_timestamp = now

    #---------------------------------------------------------------
