#ifndef DETECTOR_H
#define	DETECTOR_H

#define DETECTOR_DEBUG

#include <math.h>
#include "detector_data.h"
#include "list.h"
#include "cell.h"
#include "matrix.h"
#include "element.h"
#include "dtw.h"
#include "mlp.h"
#include "dictionary.h"

#ifdef METACENTRUM
    #define DETECTOR_INFINITY pow(2, sizeof(double)*8-1)
#else
    #define DETECTOR_INFINITY INFINITY
#endif


/*
 * Vytvori strukturu kde jsou ulozena jednotliva okna.
 */
detector_window *detector_window_alloc (unsigned int n);

/*
 * Vymaze z pameti DF.
 */
void detector_window_free (detector_window *df);

/*
 * Vlozi do prubehu jednotlivych oken okno FRAME (M x 1). Nastaveni prubehu oken
 * je ulozeno v OPT.
 */
int detector_window_add (detector_window *df, matrix *frame, detector_list_opt *opt);


/*
 * Vrati radkovou matici vzdalenosti okna od slovni tridy. Ve sloupcich jsou
 * vypocitane vzdalenosti promluvy DW od slova ve slovniku pomoci metody K
 * nejmensich sousedu.
 */
matrix *detector_class_distances (dictionary_class *word_class, detector_window *dw, detector_list_opt *opt, unsigned int K);

/*
 * Vypocita hodnotu matice pomoci metody K-NN sousednich vzdalenosti.
 * Najde ve sloupcove matici CL_DIST K nejmensich hodnot a vrati jejich prumer.
 * Pokud je v matici min radku nez K tak se vzdalenost vypocita jako prumer
 * vsech hodnot.
 */
matrix * detector_k_nn (matrix *cl_dist, unsigned int K);

/*
 * Vypocita matici vzdalenosti jednotlivych slovnich trid slovniku DICT od
 * jednotlivych oken nastavenych v OPT a ulozenych v DW.
 */
matrix *detector_dict_distance (dictionary *dict, detector_window *dw, detector_list_opt *opt, unsigned int K);

/*
 * Vrati matici vzdalenosti slova od aktualni pozice v signalu.
 */
matrix *detector_distance_weight_multiply (matrix *dist, matrix *weight);

/*
 * Projede matici FRAMES a vypocita vzdalenosti trid k jednotlivym oknum.
 * FRAMES - matice promluvy
 * OPT - nastaveni oken
 * DICT - slovnik
 * STEP - casovy skok ve FRAMES (o kolik sloupcu se ma posounout pri vypoctu nasledujici casti promluvy)
 * K - vypocet vzdalenosti tridy k promluve podle K-NN nejmensich sousedu
 */
matrix **detector_words_distances (matrix *frames, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, unsigned int *n);


/*
 * Vypocita z prubehu vzdalenosti D pomoci vah WEIGHTS, vzdalenosti slov.
 */
matrix *detector_word_proces(matrix **D, unsigned int n, matrix *weights);

/*
 * Vrati matici kde v jednotlivych radcich jsou prubehy vzdalenosti slov ve slovniku od promluvy.
 *
 * SEN - Veta
 * OPT - nastaveni oken
 * DICT - slovnik
 * STEP - casovy skok ve FRAMES (o kolik sloupcu se ma posounout pri vypoctu nasledujici casti promluvy)
 * K - vypocet vzdalenosti tridy k promluve podle K-NN nejmensich sousedu
 * WEIGHTS - prislusne vahy slov k jednotlivym oknum v OPT
 */
matrix *detector_word_process(matrix *sen, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, matrix *weights);
matrix *detector_word_process_1(sentence *sen, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, matrix *weights);

/*
 * To same jako funcke detector_word_process_1(...) ale SENS je pole vet a N je pocet vet v tomto poli.
 */
matrix **detector_word_process_2(sentence **sens, unsigned int n, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, matrix *weights);

/*
 * Z dane matice vzdalenosti slov k ramcum se ziska jedna hodnota pomoci vahovaci
 * matice WEIGHT
 */
matrix * detector_words_value (matrix *word_distance, matrix *weight);

/*
 * 
 */
matrix *detector_word_detect (matrix *sig, dictionary *dict, matrix *treshold);

/*
 * Navrhne prah jednotlivych slov podle pozice ve vete.
 */
matrix *detector_determine_treshold(sentence *sen, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, mlp *net);

/*
 * Vypocita matici 2 x N, kde v prvnim radku je minimalni vzdalenost
 * detekovaneho slova a v druhem minimalni vzdalenost detekovaneho slova mimo
 * hranice slova ve vete minimalnich a maximalnich vzdalenosti. 
 */
matrix *detector_treshold_stats(sentence *sen, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, mlp *net, matrix *weights);
matrix **detector_treshold_stats2(sentence **sens, unsigned int n, dictionary *dict, detector_list_opt *opt, unsigned int step, unsigned int K, mlp *net, matrix *weights);

/*
 * Navrhne treshold na zaklade statistik STATS.
 */
matrix *detector_design_treshold(matrix **stats, unsigned int n);

/*
 * Vypocita skore uspesnosti detekce slov ze slovniku DICT ve vetach SENS o
 * poctu N. Parametrem detekce slov je prah detekce TRESHOLD. Vypocet probiha na
 * prubehu vzdalenosti slov ve vete PROCESS. H je velikost hranice z kazde strany
 * okolo pocatku slova, kde by melo byt detekovano (pod prahem). Do posledni
 * argumentů POS, NEG a MISS je ulozen pocet slov detekovanych spravne, pocet
 * detekovanych spatne a pocet nedetekovanych.
 */
double detector_WER(matrix *ISDN);
matrix *detector_quick_WER_2(matrix **process, sentence **sens, unsigned int n, dictionary *dict, matrix *treshold, double tol);
matrix *detector_quick_WER(matrix *detection, sentence *sen, dictionary *dict, double tol);
matrix *detector_WER_ISD(matrix *word_process, matrix *detection);
matrix *detector_WER_Insections(matrix *word_process, matrix *detection);
matrix *detector_WER_Deletions(matrix *word_process, matrix *detection);

/*
 * Z prubehu vzdalenosti slov k slvnim tridam PROCCES z vet SENS o poctu N se
 * stanovi uspesnost detekce slov ze slovniku DICT podle skore. Metoda vyzkousi
 * N_TEST moznosti, z nichz kazda lezi mezi minimalni a maximalnim prahem
 * TRESHOLDMIN a TRESHOLDMAX. Funkce vraci nejlepsi reseni. H viz. vysvetleni
 * funkce DETECTOR_SCORE(...)
 */
matrix *detector_process_stats(matrix **process, unsigned int n);
matrix **detector_treshold_try(matrix **process, sentence **sens, unsigned int n, matrix *tresholdMin, matrix *tresholdMax, dictionary *dict, unsigned int n_tests, double tol);


#endif