import cv2
import matplotlib as plt
import numpy as np
import requests
import ParkingBlock as PB
import math
import xml.etree.cElementTree as ET
import glob
from copy import deepcopy
import TimeHandler as TH
import ImageAnalyser as IA

parkingLotSize = 200
hours = None
time_format = None

def readParkingImage(path):
    img = cv2.imread(path)
    global hours
    hours = TH.get_time_from_image_name(path)
    global time_format
    time_format = TH.get_time_format(hours)
    resized_img = IA.resize_to_default(img)
    return resized_img

def get_cropped_size(path,count):
    """
    input: start of path of mask file and count of masks
    output: print cropped blocks sizes
    """
    count = 10
    i = 1
    while (i<=count):
        imgName = path+"PM_"+str(i)+".jpg"
        print(imgName)
        img = readParkingImage(path)
        countBlack,countWhite,gap = get_mask_size_from_image(img)
        print(str.format("{0}: image: {1} Size: {2} Black {3} White {4} Gap {5}",i,imgName,img.shape[0]*img.shape[1],countBlack,countWhite,gap))
        i+=1
        
def round_percentage_by_five(p):
    """
    input: 0 <= n <= 1
    output: 0 <= res <= 100
    """
    res = -1
    if p%10!=0:
        lowerP = int(p*10)/10
        higherP = int((p*10)+1)/10
        if p - lowerP <= 0.025:
            res = lowerP * 100
        elif p - lowerP <= 0.075:
            res = ((higherP+lowerP+0.001)/2)*100
        else:
            res = higherP * 100
    return int(res)
        
def get_black_pixels_percentage_from_list(countWhite,img,croppedSize,fullSize):
    """
    ** for process preperation only ** 
    param lst : list of pixels and image
    """
    #print("fullSize: " + str(fullSize))
    #print("croppedSize: " + str(croppedSize))
    dif = fullSize - croppedSize
    #print("difference: " + str(dif))
    percentage = (countWhite/croppedSize)*100
    return 100 - percentage

def identify_parking_spot(img,block):
    """
    
    """
    out,minX,minY,maxX,maxY, = grayscale_image(img,block)
    countWhite,countBlack = count_white_and_black(minX,minY,maxX,maxY,out)
    #print("Count Black: "+str(countBlack))
    #print("Count White: "+str(countWhite))
    #print("Sum: " +str(countBlack+countWhite))
    return countWhite,out
def grayscale_image(img,block):
    out = img
    poly = block.poly
    minX,minY,maxX,maxY = getPolyRange(poly)
    whitePixelsList = []
    pts = np.array(poly,dtype=np.int32)
    mask = np.zeros((img.shape[0], img.shape[1]))
    cv2.fillConvexPoly(mask, pts, 1)
    mask = mask.astype(np.bool)
    out = np.zeros_like(img)
    out[mask] = img[mask]

    grayscaled = cv2.cvtColor(out,cv2.COLOR_BGR2GRAY)
    out = cv2.adaptiveThreshold(grayscaled,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,255,0)
    return out,minX,minY,maxX,maxY
def count_white_and_black(minX,minY,maxX,maxY,out):
    countWhite = countBlack = 0
    otype = 'notlist'
    for x in range(minX,maxX):
        for y in range(minY,maxY):
            px = out[y,x]
            if otype == 'list':
                if px[0]==255 and px[1]==255 and px[2]==255:
                    countWhite+=1
                elif px[0]==0 and px[1]==0 and px[2]==0:
                    countBlack+=1
            else:
                if px==0:
                    countBlack+=1
                else:
                    countWhite+=1
            
    return countWhite,countBlack
def calc_rectOfPoly_size(poly):
    """
    ** for process preperation only ** 
    input: poly of points
    output: number of pixels in range
    """
    minX,minY,maxX,maxY = getPolyRange(rect)
    size = (maxX - minX) * (maxY - minY)
    return size


def create_road_colors_collection(images):
    dicOfColors = dict();
    for image in images:
        height,width,depth = image.shape
        for y in range(0,height):
            for x in range(0,width):
             dicOfColors.update({tuple(image[y,x]):True})
    del dicOfColors[(255,255,255)]
    return dicOfColors

def mark_setOfColors_with_bright_color(image,dicOfColors):
    height,width,depth = image.shape
    for y in range(0,height):
        for x in range(0,width):
            if  dicOfColors.get(tuple(image[y,x]),False):
                                image[y,x] = [255,255,255]
            else:
                image[y,x] = [0,0,0]
    return image
def getPolyRange(poly):
    """
    ** for process preperation only ** 
    input: polygon points
    output: tuple in the following format: (minX,minY,maxX,maxY)
    """
    minX,minY = maxX,maxY = tuple(poly[0])

    for point in poly:
        curX,curY = point
        if curX > maxX:
            maxX = curX
        elif curX < minX:
            minX = curX
        if curY > maxY:
            maxY = curY
        elif curY < minY:
            minY = curY
            
    return minX,minY,maxX,maxY

def draw_squares(img):
    height,width,depth = img.shape
    x = y = 0
    while y < height - 10:
        while x < width - 10:
            check_square_isblack(img,x,y,x+10,y+10)
            x+=10
        y+=10
        x = 0
    return img
            
def check_square_isblack(img,minX,minY,maxX,maxY):
    blackCount = whiteCount = 0
    for y in range (minY,maxY):
        for x in range(minX,maxX):
            if IA.is_black(img[y,x]):
                blackCount+=1
            else: whiteCount+=1
    size = blackCount+whiteCount
    if blackCount>20:
        for y in range (minY,maxY):
            for x in range(minX,maxX):
                img[y,x] = [0,0,0]

        
def get_availability_percentage_from_image(carsImagePath):
    print ("Image Path: " +carsImagePath)
    carsCount = 0 
    img = readParkingImage(carsImagePath)
    cv2.imwrite('original.jpg',img)
    dicOfColors = TH.xml_to_dic(time_format)
    listOfBlocks = PB.parkingBlocksList
    brightRes = mark_setOfColors_with_bright_color(img,dicOfColors)
    cv2.imwrite('afterDicOfColors.jpg',brightRes)
    print("Hours: "+str(hours))
    if hours==20:
        return 10
    for block in listOfBlocks:
        carsCount += iterate_block(block,carsImagePath,brightRes)
    usage_percentage = carsCount/parkingLotSize
    usage_percentage_roundbyfive = round_percentage_by_five(usage_percentage)
    print ("parking lot cars: " + str(carsCount))
    print ("usage rounded: " + str(usage_percentage_roundbyfive))
    return usage_percentage_roundbyfive
def iterate_block(block,carsImagePath,gsImage):
    img = readParkingImage(carsImagePath)
    print("Index: " +str(block.index))
    calc_block = manipulate_block_by_time_format(block)
    gsImage = draw_squares(gsImage)
    cv2.imwrite('withsquares.jpg',gsImage)
    whitePixelsCount,outRes = identify_parking_spot(gsImage,calc_block)
    blackRes = get_black_pixels_percentage_from_list(whitePixelsCount,outRes,block.croppedBlockSize,block.rectSize)
    curCarsCount = calc_block.compute_cars(blackRes)
    print("Cars count: "+str(curCarsCount))
    print("black percentage: "+ str(blackRes) + "%\n")
    return curCarsCount

def analyse_images(dirPath):
    listOfImagesPath = IA.load_multiple_images_path(dirPath,100)
    for imagePath in listOfImagesPath:
        get_availability_percentage_from_image(imagePath)

def manipulate_block_by_time_format(block):
    changeMin = changeMax = changeLimits = 0
    
    copy_block = deepcopy(block)
    if time_format == 'Morning':
        changeLimits = 10
        if copy_block.index == 9:
            changeLimits+=10
        elif copy_block.index in [1,4,6]:
            changeLimits+=8
    if time_format == 'Day':
        changeLimits = -10
        if copy_block.index in [2,9]:
            changeMin=10
        elif copy_block.index in [10]:
            changeMax = 15
        elif copy_block.index in [8]:
            changeMin = 20
        elif copy_block.index in [1,4,6]:
            changeLimits = 4
            if hours==15:
                changeLimits+=4
            elif hours<=12:
                changeLimits = -10
            elif hours>15:
                changeLimits-=4
    elif time_format == 'Dawn':
        if copy_block.index == 1:
            changeLimits = 14
        if copy_block.index == 9:
            changeLimits = 5
    copy_block.Min += changeLimits + changeMin
    copy_block.Max += changeLimits + changeMax
    return copy_block

def run():
    imgPath = "AcademicParkingPics/7-10/2016-08-17T06_52.37.610.jpg"
   # img = readParkingImage(imgPath)
    get_availability_percentage_from_image(imgPath)
    #analyse_images("AcademicParkingPics/21-23/")



