import os
import time
import cv2
import threading
from PIL import Image

from config import cfg


_capturethreadsinglelock = False

class _capturethread(threading.Thread):
    def __init__(self):
        self.running = False
        self.directory = ""
        self.prename = ""
        self.bufsize = 0
        self.duration = 0.0
        
        threading.Thread.__init__(self)

    
    def run(self):
        global _capturethreadsinglelock
        if _capturethreadsinglelock:
            return
        _capturethreadsinglelock = True
        self.running = True
            
        bufcount = 1
        while self.running :
            start_time = time.time()
            
            filename = '%s%d.jpg' % (self.prename, bufcount)
            hr = Camera.CaptureImage(self.directory, filename)
            if hr < 0:
                print('Zhi Error: Capture image from camera failed')
                break
            
            end_time = time.time()
            jobduration = end_time - start_time
            (quo, rem) = divmod(jobduration, self.duration)
            bufcount = (bufcount + quo + 1) % self.bufsize
            if bufcount == 0 :
                bufcount = self.bufsize
            waittime = self.duration - rem
            if waittime > 0 :
                time.sleep(waittime)
                
        self.running = False      # for break
        _capturethreadsinglelock = False

    
    def IsRunning(self):
        return _capturethreadsinglelock

    
    def StopThread(self):
        self.running = False
        while(_capturethreadsinglelock):
            time.sleep(1)
            

class _camera():
    def __init__(self):
        self.cap = None
        self.cthread = None
        self.dnumber = cfg.getint("device","devicenumber")
        self.pixelformat = cfg.get("device","pixelformat")
        self.framewidth = cfg.getint("device","framewidth")
        self.frameheight = cfg.getint("device","frameheight")
        self.autofocus = cfg.getint("device","autofocus")

    
    def __del__(self):
        if self.cap is not None:
            if self.cap.isOpened():
                self.CloseCamera()

    
    def IsOpened(self):
        if self.cap is None:
            return False
            
        return self.cap.isOpened()

    
    def OpenCamera(self):
        if self.IsOpened():
            return True
            
        self.cap = cv2.VideoCapture(self.dnumber)
        if self.cap.isOpened():
            self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
            self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*self.pixelformat))
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.framewidth)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.frameheight)
            self.cap.set(cv2.CAP_PROP_AUTOFOCUS, self.autofocus)
            
            return True
        else:
            print("Zhi Error: Cann't open carema")
            return False

    
    def CloseCamera(self):
        if self.IsOpened():
            if self.cthread is not None:
                self.cthread.StopThread()
                self.cthread = None
                
            self.cap.release()
            cv2.destroyAllWindows()
            self.cap = None

    
    def CaptureImageBuf(self):
        if not self.IsOpened():
            return (-1, None)
            
        ret, frame = self.cap.read()
        if not ret:
            print("Zhi Error: Cann't capture Image from camera")
            return (-2, None)

        # read second frame from camera, because CAP_PROP_BUFFERSIZE just cann't be setting to 0(last is 1), so there is 1 buffer frame shoud be give up.
        ret, frame = self.cap.read()
        if not ret:
            print("Zhi Error: Cann't capture Realtime Image from camera")
            return (-2, None)

        return (0, frame)

    
    def CaptureImage(self, directory, filename):
        (hr, frame) = self.CaptureImageBuf()
        if hr == -1:
            return -1
        elif hr == -2:
            return -2

        filedir = os.path.join(directory, filename)
        if not cv2.imwrite(filedir, frame):
            print('Zhi Error: Can not save image to folder')
            return -3
            
        return 0

    
    def CaptureImagesStart(self, directory, prename, bufsize, duration):
        if not self.IsOpened():
            return -1
            
        if self.cthread is None :
            self.cthread=_capturethread()
            self.cthread.directory = directory
            self.cthread.prename = prename
            self.cthread.bufsize = bufsize
            self.cthread.duration = duration   #s, float
            self.cthread.start()
            return 0

        if self.cthread.IsRunning() :
            print("Zhi Error: Capture is running when start it")
            return -2

        print("Zhi Error: Capture is bock when start it")
        return -3

    
    def CaptureImagesStop(self):
        if self.cthread is None:
            print("Zhi Error: Capture is not inited when stop it")
            return -1
            
        if not self.cthread.IsRunning():
            print("Zhi Error: Capture is not started when stop it")
            return -2
            
        self.cthread.StopThread()
        self.cthread = None
        return 0
    

Camera = _camera()

