#!/usr/bin/env python
# coding=utf-8
"""
Online Acoustic Monitoring

Usage:
    acoustics.py [options]
    acoustics.py (-h | --help)

Options:
    -d DET_ID       Detector ID
    -n N_DUS        Number of DUs
    -o PLOT_DIR     The directory to save the plot 
    -h --help       Show this screen.

"""
import numpy as np
import matplotlib.pyplot as plt
import time
import os
import matplotlib
from matplotlib import colors
from datetime import datetime
from docopt import docopt
import km3pipe as kp


def diff(first, second):
    second = set(second)
    return [item for item in first if item not in second]


args = docopt(__doc__)

detid = args['-d']
directory = args['-o']
N_DUS = args['-n']
N_DUS = int(N_DUS)

db = kp.db.DBManager()
sds = kp.db.StreamDS()

ACOUSTIC_BEACONS = [12, 14, 16]
N_DOMS = 18
N_ABS=3
DOMS = range(N_DOMS + 1)
DUS = range(1, N_DUS + 1)

TIT = 600 # Time Interval between Trains of acoustic pulses)
SSW = 160 # Signal Security Window (Window size with signal)

check = True
while check:
    
    table = db.run_table(detid)
    minrun = table["RUN"][len(table["RUN"]) - 1]	
    ind, = np.where((table["RUN"] == minrun))
    mintime1 = table['UNIXSTARTTIME'][ind]
    mintime = mintime1.values
    maxrun = table["RUN"][len(table["RUN"]) - 1]
    now = time.time()
    if (now - mintime/1000) < TIT:
        minrun = table["RUN"][len(table["RUN"]) - 1] - 1 
    print(now)

    N_Pulses_Indicator = [] # Matrix indicating how many pulses each piezo reveals
    for du in DUS:
        N_Pulses_Indicator_DU = [] # Array indicating for each DU how many pulses each piezo reveals.
        for ab in ACOUSTIC_BEACONS:
            for dom in DOMS:
                try:
                    domID = db.doms.via_omkey((du, dom), detid).dom_id
                    toas_all = sds.toashort(detid = detid, minrun = minrun, maxrun = maxrun, domid = domID, emitterid = ab) 
                
                    QF_abdom = toas_all["QUALITYFACTOR"]
                    UTB_abdom = toas_all["UNIXTIMEBASE"]
                    TOAS_abdom = toas_all["TOA_S"]
                    UTB_abdom = UTB_abdom.values
                    up = np.where(UTB_abdom>(now-TIT))
                    down = np.where(UTB_abdom<(now))
                    intr = np.intersect1d(up,down)
                    UTB_abdom = UTB_abdom[intr]
                    QF_abdom = QF_abdom[intr]                
                    QF_abdom = QF_abdom.values
                    QFlist = QF_abdom.tolist()
                    QFlist.sort(reverse = True)
                    QF_max = max(QF_abdom)
                    QF_max_index = np.where(QF_abdom == QF_max)
                    UTB_signal_min = UTB_abdom[QF_max_index] - SSW/2
                    UTB_signal_max = UTB_abdom[QF_max_index] + SSW/2
                    temp1 = np.where(UTB_abdom > (UTB_signal_min[0]))
                    temp2 = np.where(UTB_abdom < (UTB_signal_max[0]))
                    inter = np.intersect1d(temp1, temp2)
                    inter = inter.tolist()
                    signal_index = inter
                    QF_abdom_index = np.where(QF_abdom)
                    all_data_index = QF_abdom_index[0].tolist()
                    noise_index = diff(all_data_index, signal_index)
                    SIGNAL = QF_abdom[signal_index] 
                    UTB_SIGNAL = UTB_abdom[signal_index]
                    NOISE = QF_abdom[noise_index] 
                    NOISElist = NOISE.tolist()
                    NOISElist.sort(reverse = True)
                    noise_threshold = max(NOISE) 
                    
                    # First filter: 22 greatest
                    Security_Number = 22 # To be sure to take all the pulses
                        
                    SIGNAL = SIGNAL.tolist()
                    SIGNAL_OLD = np.array(SIGNAL)
                    SIGNAL.sort(reverse = True)
                    QF_first = SIGNAL[0:Security_Number]
                    
                    # Second filter: delete duplicates
                    
                    QF_second = np.unique(QF_first)
                    QF_second = QF_second.tolist()
                    QF_second.sort(reverse = True)
                    
                    # Third filter: If there are more than 11 elements I will eliminate the worst
                    
                    if len(QF_second) > 11:
                        QF_second = np.array(QF_second)
                        QF_third = [k for k in QF_second if (np.where(QF_second == k)[0][0] < 11)]
                    else:
                        QF_third = QF_second
                    
                    # Fourth filter: I remove the data if it is below the maximum noise
                    
                    QF_fourth = [k for k in QF_third if k > (noise_threshold + (5*np.std(NOISE)))]
                    
                    # Fifth filter: Check if the clicks are interspersed in the right way
                    
                    Q = []
                    for q in np.arange(len(QF_fourth)):
                        Q.append(np.where(SIGNAL_OLD == QF_fourth[q])[0][0])
                    UTB_fourth = np.array(UTB_SIGNAL.tolist())[Q]
                    UTB_fourth_l = UTB_fourth.tolist()
                    D = []
                    for g in np.arange(len(UTB_fourth_l)):
                        if ((np.mod((UTB_fourth_l[g] - UTB_fourth_l[0]), 5) > 0.5 and np.mod((UTB_fourth_l[g] - UTB_fourth_l[0]), 5) < 4.5) or (np.mod((UTB_fourth_l[g] - UTB_fourth_l[0]), 5)>5)):
                           D.append(g)
                    for d in sorted(D, reverse = True):
                        del QF_fourth[d]  
                    QF_fifth = QF_fourth
                    QF_OK = QF_fifth
                    NUM = len(QF_OK) # Number of pulses
                    print(NUM)
                    
                    if (NUM > 7):
                        N_Pulses_Indicator_DU.append(1.5)
                    elif (NUM < 8 and NUM > 3):
                        N_Pulses_Indicator_DU.append(0.5)
                    elif (NUM < 4 and NUM > 0):
                        N_Pulses_Indicator_DU.append(-0.5)
                    elif (NUM == 0):
                        N_Pulses_Indicator_DU.append(-1.5)

                        
                except (TypeError, ValueError): # TypeError if no data found for a certain piezo, ValueError if there are zero data for a certain piezo
                    N_Pulses_Indicator_DU.append(-1.5)
                    
        N_Pulses_Indicator.append(N_Pulses_Indicator_DU)
        
       
    fig = plt.figure()
    ax = fig.add_subplot(111)
    N_doms = 18
    doms = range(N_doms + 1)
    L = len(doms)
    
    duab = []
    DUs = []
    for du in range(N_DUS):
        duabdu = []
        duab1 = (du+0.9)*np.ones(L)
        duab2 = (du+1)*np.ones(L)
        duab3 = (du+1.1)*np.ones(L)
        duabdu.append(duab1)
        duabdu.append(duab2)
        duabdu.append(duab3)
        duab.append(duabdu)
        DUs.append(np.array(N_Pulses_Indicator[du]))
            
    ind = np.where(DUs[1] < 1000)
    iAB1 = np.where(ind[0] < L)
    iAB2_up = np.where(ind[0] > (L - 1))
    iAB2_down = np.where(ind[0] < 2*L)
    iAB2 = np.intersect1d(iAB2_up, iAB2_down)
    iAB3 = np.where(ind[0] > (2*L - 1))
    
    colorsList = [(0, 0, 0), (1, 0.3, 0), (1, 1, 0), (0.2, 0.9, 0)]
    CustomCmap = matplotlib.colors.ListedColormap(colorsList)
    bounds = [-2, -1, 0, 1, 2]
    norma = colors.BoundaryNorm(bounds, CustomCmap.N)
    for du in range(N_DUS):
        for ab in range(N_ABS):
            color = ax.scatter(duab[du][ab], doms, s = 20, c = DUs[du][iAB1], norm=norma, marker = 's', cmap = CustomCmap);
            color = ax.scatter(duab[du][ab], doms, s = 20, c = DUs[du][iAB2], norm=norma, marker = 's', cmap = CustomCmap);
            color = ax.scatter(duab[du][ab], doms, s = 20, c = DUs[du][iAB3], norm=norma, marker = 's', cmap = CustomCmap);
    
    cbar = plt.colorbar(color)
    cbar.ax.get_yaxis().set_ticks([])
    for j, lab in enumerate(['$0. pings$', '$1-3 pings$', '$4-7 pings$', '$>7. pings$']):
        cbar.ax.text(3.5, (2*j + 1)/8.0, lab, ha = 'center', va = 'center')
    cbar.ax.get_yaxis().labelpad = 18
    
    matplotlib.pyplot.xticks(np.arange(1, N_DUS + 1, step = 1))
    matplotlib.pyplot.yticks(np.arange(0, 19, step = 1))
    matplotlib.pyplot.grid(color = 'k', linestyle = '-', linewidth = 0.2)
    ax.set_xlabel('DUs', fontsize = 18)
    ax.set_ylabel('Floors', fontsize = 18)
    ts = now + 3600
    DATE = datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
    ax.set_title(r' %.16s Detection of the pings emitted by autonomous beacons' %DATE, fontsize = 10)                  
        
    my_path = os.path.abspath(directory) 
    my_file = 'Online_Acoustic_Monitoring.png'
    
    fig.savefig(os.path.join(my_path, my_file))    
                                        
    print(time.time())
                               
    check = False
    check_time = time.time() - now
    print(check_time)
       
    time.sleep(abs(TIT - check_time))
    check = True