#!/usr/bin/env python

import unittest
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from DaviesBouldin import GetDaviesBouldin
import K_Means
import GeneticCore
from sklearn.datasets.samples_generator import make_circles
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Cambria Math'] + plt.rcParams['font.serif']
import random

# k = chromosomeSize  ( k = Centroid ) [| C1 | C2 | C3 |]
# popSize = k*chromosomeSize
# geneSet = X
# length = k
# get_fitness = Euclidian distance, DaviesBouldin,
# objective function = argmin_{ci \in C} dist(ci, x)^2
# problem set = minimize sum_{k =1}^{K}sum_{c \in C} || x - mu||^2 , with respect to DB Index = 0, avr dist C, k

def appendData(X, chromosome, k):
    clusters = [[] for l in range(k)]
    for individum in X:
        for i, gene in enumerate(chromosome):
            if (K_Means.euclidianDistance(individum, gene)) <= min(K_Means.euclidianDistance(individum, gene) \
                                                                   for gene in chromosome):
                clusters[i].append(individum)
    return clusters

def getFitness(X, chromosome, k):

    clusters = appendData(X, chromosome, k)
    centroids = [[] for j in range(k)]
    for i, chromosom in enumerate(chromosome):
        centroids[i].append([chromosom])
    DB = GetDaviesBouldin(centroids, clusters, k)
    db = [DB.dbIndex]
    interLen = [DB.interLenSum]
    roids = DB.Centroids

    centre = []
    for i, new_centr in enumerate(roids):
        centre.extend(new_centr)
    centers = [centre[i] for i in range(len(centre))]

    return db, interLen, centers

def plot_solution_real(population, k, X, dataset):
    best_fitness, index = (min([(np.ma.masked_invalid(v), i) for i, v in enumerate(population.interlen)]))
    centr = population.Chromosomes[index]
    clusters = appendData(X, centr, k)
    datas = pd.DataFrame(dataset)
    print(datas)
    for i, cluster in enumerate(clusters):
        print("Blízká hodnota hazardu {}:".format(i))
        a, b, c, d, e, ff = zip(*cluster)
        for cislo in ff:
            for j, jmeno in enumerate(datas.h):
                if datas.h.loc[j] == cislo:
                    print(datas.iloc[j][0])


def plot_solution(population, k, X):
    best_fitness, index = (min([(np.ma.masked_invalid(v), i) for i, v in enumerate(population.interlen)]))
    centr = population.Chromosomes[index]
    clusters = appendData(X, centr, k)
    # ZOBRAZENÍ ŘEŠENÍ
    paired = plt.get_cmap('Paired')
    colors = iter(paired(np.linspace(0, 1, k)))
    for i, cluster in enumerate(clusters):
        x, y = zip(*cluster)
        plt.scatter(x, y, color=next(colors))

    centroids = [[] for j in range(k)]
    for i, centroid in enumerate(centroids):
        centroid.append(np.mean(clusters[i], axis=0))
        a, b = zip(*centroid)
        plt.scatter(a, b, color="black", marker="*", s=60)

    plt.xlabel('$Vzdálenost$')
    plt.ylabel('$Rychlost$')
    plt.show()

# TESTOVACÍ TŘÍDA
class GeneticsCase(unittest.TestCase):
    def test(self):
        # TEST 1
        #dataset = pd.read_csv("data_1024.csv",sep="\t")
        #f1 = dataset['Distance_Feature'].values
        #f2 = dataset['Speeding_Feature'].values
        #X = np.array(list(zip(f1, f2)))
        #plt.scatter(dataset['Distance_Feature'], dataset['Speeding_Feature'])
        #plt.xlabel('$Vzdálenost$')
        #plt.ylabel('$Rychlost$')

        # TEST 2
        #X, y = make_circles(n_samples=400, factor=.3, noise=.05)
        #plt.scatter(X[:, 0], X[:, 1])
        #plt.show()

        # TEST 3
        # realný provoz
        dataset = pd.read_csv("data_1025.csv", sep=" ")
        #print(dataset)
        f1 = dataset['a'].values
        f2 = dataset['b'].values
        f3 = dataset['c'].values
        f4 = dataset['f'].values
        f5 = dataset['g'].values
        f6 = dataset['h'].values
        X = np.array(list(zip(f1, f2, f3, f4, f5, f6)))

        self.computeGeneticKmeans(X, 3, 10, dataset)

    @staticmethod
    def computeGeneticKmeans(X, k, popSize, dataset):
        def fnGetFitness(chromosome):
            return getFitness(X, chromosome, k)

        geneSet = X
        population = GeneticCore.generate_population(k,geneSet, popSize, fnGetFitness)
        pop = GeneticCore.generate_best(population, fnGetFitness, geneSet, k)
        #print(pop)
        plot_solution_real(pop, k, X, dataset)
        #plot_solution(pop, k, X)

def main():
    unittest.main()
    import sys
    sys.modules[__name__].__dict__.clear()

if __name__ == '__main__':
    main()

