import numpy as np
import cv2
import os
import time

def sendAPICall(APICall):      #function to write on the shared callAPI.txt file
    fileCallData = open('shared data\\callAPI.txt','w')
    fileCallData.write(APICall+'\n')

open('shared data\\returnAPI.txt','w').close()      #clear shared returnAPI.txt file
endProg, retPD, retLensMov, retNoOp=False, False, False, False
clockCycle, numOfTimePoints, stepsAllowedPerTimePoint, PDoptimal , lensPosList= 0, 0, 0, 0, []
fourcc = cv2.VideoWriter_fourcc(*'XVID')
while (True):      #listening to API return values
    while(os.stat('shared data\\returnAPI.txt').st_size != 0):      #true if API writes any return values on the shared returnAPI.txt file
        open('shared data\\callAPI.txt','w').close()      #clear shared returnAPI.txt file
        fileRetData = open('shared data\\returnAPI.txt','r')      #read API return values from the shared returnAPI.txt file
        inData=(fileRetData.read()).split(',')
        print(inData)
        open('shared data\\returnAPI.txt', 'w').close()      #clear shared returnAPI.txt file
        ######
        if inData[0]=='start':      #true once the API starts (only for the first time) 
            #API returns all the API parameters
            clockCycle, lensPos, timePoint, scene, numOfTimePoints, focusStackSize, AFobjective, sharpnessMeasure, kernelSize, roh, stepsAllowedPerTimePoint = int(inData[1]), int(inData[2]), int(inData[3]), inData[4], int(inData[5]), int(inData[6]), inData[7], inData[8], int(inData[9]), int(inData[10]), int(inData[11])
            scNum, rNum, shNum, kNum =3, 3, 0, 0      #scNum: scne number (3: Scene 4), rNum: region selected (3:face region), shNum: sharpness measure (0:Sobel), and kNum: kernel size (0: size of 3)
            sendAPICall('setScene('+str(scNum)+')')      #select Scene 4
            time.sleep(15)      #wait for the API to upload the scene selected to the main memory. It takes time becuase we upload the whole scene of 50xn (scene's time points:51,61,71,or91) images to the main memeory for faster implementation
            open('shared data\\callAPI.txt','w').close()
            sendAPICall('setRegion('+str(rNum)+')')      #set region to global
            time.sleep(1)
            open('shared data\\callAPI.txt','w').close()
            sendAPICall('setSharpMeasure('+str(shNum)+')')      #set sharpness measure to Sobel
            time.sleep(1)
            open('shared data\\callAPI.txt','w').close()
            sendAPICall('setKernelSize('+str(kNum)+')')      #set kernel size to 3
            time.sleep(1)
            open('shared data\\callAPI.txt','w').close()
            sendAPICall('recordScript()')      #start recording API calls
            open('shared data\\returnAPI.txt', 'w').close()
            currentImage=cv2.imread('shared data\\img.png')      #read the image returned by the API, the user will get an image at each clock cycle
            video = cv2.VideoWriter('objective videos\\AF_Scene'+str(scNum+1)+'_obj'+str(rNum)+'.avi', fourcc, 70, (currentImage.shape[1], currentImage.shape[0]))
            time.sleep(1)
        elif inData[0]=='end':      #API returns 'end' when the scene ends (after the last time point in the scene)
            sendAPICall('endScript()')      #stop recording API calls and save the metadata about the performance (e.g., total number of lens movements)
            open('shared data\\returnAPI.txt', 'w').close()
            endProg=True
            break
        elif retPD:      #retuen of callPD()
            clockCycle, timePoint, currentImage, lensPos, PDoptimal=int(inData[0]), int(inData[1]), cv2.imread('shared data\\img.png'), int(inData[2]), int(inData[3])      #return current clock cycle, gobal time (current time point), image, lens position, and optimal lens position
            retPD=False
        elif retLensMov:      #retuen of moveLensForward() and moveLensBackward()
            clockCycle, timePoint, currentImage, lensPos=int(inData[0]), int(inData[1]), cv2.imread('shared data\\img.png'), int(inData[2])      #return current clock cycle, gobal time (current time point), image, and lens position
            retLensMov=False
        elif retNoOp:      #retuen of noOp()
            clockCycle, timePoint, currentImage=int(inData[0]), int(inData[1]), cv2.imread('shared data\\img.png')     #return current clock cycle, gobal time (current time point), and current image
            retNoOp=False
        ######
        if clockCycle%stepsAllowedPerTimePoint==0:      #callPD(0) when time point ti incremented (at each time point)
            sendAPICall('callPD(0)')
            retPD=True      #To read retuen values of callPD(0)
        elif PDoptimal>lensPos:
            sendAPICall('moveLensForward()')
            retLensMov=True      #To read retuen values of moveLensForward()
        elif PDoptimal<lensPos:
            sendAPICall('moveLensBackward()')
            retLensMov=True      #To read retuen values of moveLensBackward()
        else:
            sendAPICall('noOp()')
            retNoOp=True      #To read retuen values of noOp()
        lensPosList.append(lensPos)      #write lens position into a list
        video.write(currentImage)      #write current image into a video object
    if endProg:
        break
np.save('AF_Scene'+str(scNum+1)+'_obj'+str(rNum), np.asarray(lensPosList))
video.release()