from colorama import init, Fore, Style
from shapely.geometry import Polygon
import cv2
import dateparser
import configargparse
import numpy as np
from datetime import datetime, timedelta
import re


import zmMagik_helpers.globals as g

#https://stackoverflow.com/a/43357954/1361529
def str2bool(v):
    if isinstance(v, bool):
       return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

def hist_match(source, template):
#https://stackoverflow.com/questions/32655686/histogram-matching-of-two-images-in-python-2-x
    olddtype = source.dtype
    oldshape = source.shape
    source = source.ravel()
    template = template.ravel()

    s_values, bin_idx, s_counts = np.unique(source, return_inverse=True,
                                            return_counts=True)
    t_values, t_counts = np.unique(template, return_counts=True)
    s_quantiles = np.cumsum(s_counts).astype(np.float64)
    s_quantiles /= s_quantiles[-1]
    t_quantiles = np.cumsum(t_counts).astype(np.float64)
    t_quantiles /= t_quantiles[-1]
    interp_t_values = np.interp(s_quantiles, t_quantiles, t_values)
    interp_t_values = interp_t_values.astype(olddtype)

    return interp_t_values[bin_idx].reshape(oldshape)

def init_colorama():
    init()

def secure_string(str):
    return re.sub(r'(((pass)(?:word)?)|(auth)|(token))=([^&/?]*)',r'\1=***',str.lower())    

def str2arr(str):
   ret = np.array(str.replace(' ',',').split(','),dtype=int).reshape(-1,2)
   return (ret)

def bold_print(text):
    print (Style.RESET_ALL+Style.BRIGHT+text+Style.RESET_ALL)

def dim_print(text):
    print (Style.RESET_ALL+Style.DIM+text+Style.RESET_ALL)

def success_print(text):
    print (Style.RESET_ALL+Fore.GREEN+text+Style.RESET_ALL)

def fail_print(text):
    print (Style.RESET_ALL+Fore.RED+text+Style.RESET_ALL)

def process_config():
    if not g.args['input'] and not g.args['eventid'] and not g.args['from'] and not g.args['to']:
        fail_print ('Error: You either need to specify an input video, or an event id, or a timeline')
        exit(1)
    if g.args['eventid'] and not ( g.args['username'] and g.args['password'] and g.args['portal'] ):
        fail_print ('Error: If you specify an event ID, you MUST specify username,password and portal')
        exit(1)
    if (g.args['from'] or g.args['to']) and not ( g.args['username'] and g.args['password'] and g.args['portal'] ):
        fail_print ('Error: If you specify a timeline you MUST specify username,password and portal')
        exit(1)    
    if g.args['mask']:
        parr = str2arr(g.args['mask'])
        if g.args['resize']:
            resize = g.args['resize']
            parr =(parr*resize).astype(int)
        g.raw_poly_mask = parr
        g.poly_mask = Polygon(parr)
    
    if g.args['find']:
        g.template = cv2.imread(g.args['find'])
        if g.args['resize']:
            rh, rw, rl = g.template.shape
            g.template = cv2.resize(g.template, (int(rw*resize), int(rh*resize)))
        g.template = cv2.cvtColor(g.template, cv2.COLOR_BGR2GRAY)


    # if either from or to is specified, populate both ranges
    # if not, leave it as None
    if g.args['to'] or g.args['from']:
        if g.args['to']:
            to_time = dateparser.parse(g.args['to'])
        else:
            to_time= datetime.now()
            
        if g.args['from']:
            from_time = dateparser.parse(g.args['from'])
            print (from_time)
        else:
            from_time = to_time - timedelta(hours = 1)

        g.args['from']= from_time.strftime('%Y-%m-%d %H:%M:%S')
        g.args['to'] = to_time.strftime('%Y-%m-%d %H:%M:%S')
        if (to_time <= from_time):
            fail_print ('ERROR: Time range from:{} to:{} is invalid '.format(from_time, to_time))
            exit(1)

    if g.args['monitors']:
        g.mon_list = [int(item) for item in g.args['monitors'].split(',')]

    if g.args['minblendarea']:
        g.min_blend_area = g.args['minblendarea']

    if not g.args['find'] and not g.args['blend'] and not g.args['annotate']:
        fail_print('You need to specify one of  --find or --blend or --annotate')
        exit(1)


def write_text(frame=None, text=None, x=None,y=None, W=None, H=None, adjust=False):
    (tw, th) = cv2.getTextSize(text, cv2.FONT_HERSHEY_PLAIN, fontScale=g.args['fontscale'], thickness=2)[0]
    loc_x1 = x
    loc_y1 = y - th - 4
    loc_x2 = x + tw + 4
    loc_y2 = y

    if adjust:
        if not W or not H:
            fail_print('cannot auto adjust text as W/H  not provided')
        else:
            if loc_x1 + tw > W:
                loc_x1 = max (0, loc_x1 - (loc_x1+tw - W))
            if loc_y1 + th > H:
                loc_y1 = max (0, loc_y1 - (loc_y1+th - H))

    cv2.rectangle(frame, (loc_x1, loc_y1), (loc_x1+tw+4,loc_y1+th+4), (0,0,0), cv2.FILLED)
    cv2.putText(frame, text, (loc_x1+2, loc_y2-2), cv2.FONT_HERSHEY_PLAIN, fontScale=g.args['fontscale'], color=(255,255,255), thickness=1)
    return loc_x1, loc_y1, loc_x1+tw+4,loc_y1+th+4