import numpy as np
import json
import itertools
import matplotlib.pyplot as plt
import random


try:
    from .mlp import Mlp
except Exception: #ImportError
    from mlp import Mlp


def process(labeld):
    res = []
    for data in labeld:
        tocuh = 1 if sum(data["touch"]) != 0 else 0
        tmp = {
            "pos": data["proprio"],
            "touch": [tocuh]
        }
        res.append(tmp)
        tmpReverse = {
            "pos": data["proprio"][16:32] + data["proprio"][0:16],
            "touch": [tocuh]
        }
        #res.append(tmpReverse)
    return res


def compar(a, b):
    for i, j in zip(a, b):
        if i != j:
            return False
    return True


def per(size, ones):
    return list(filter(lambda x: sum(x) == ones, itertools.product([0, 1], repeat=size)))


def _cost(target, outputs):
    return np.sum((target - outputs) ** 2, axis=0)

if __name__ == "__main__":
    """
    Training MLP filter on ../data.data -- rescaled raw data
    """
    test = True
    f = open("../data.data")
    rawData = json.load(f)

    rawData = process(rawData)
    random.shuffle(rawData)

    if test:
        line = int(len(rawData) * 0.75)  # test generalization
    else:
        line = len(rawData) # final training

    X = np.array([i['pos'] for i in rawData[0:line]])
    Y = np.array([i["touch"] for i in rawData[0:line]])
    testX = np.array([i['pos'] for i in rawData[line:]])
    testY = np.array([i["touch"] for i in rawData[line:]])

    inp = len(X[0])
    out = len(Y[0])
    layers = [inp, 50, 10, out]
    res = []

    print(layers)
    model = Mlp(layers)
    res = model.train(X, Y, iterations=10000)    # final train 10k iterations

    replot = plt.subplot(311)
    replot.set_title("mean sqr")
    replot.plot([i for i, _ in res])

    errplot = plt.subplot(313)
    errplot.set_title("classify error in %")
    errplot.set_ylim([-5, 105])
    errplot.plot([i for _, (i, _) in res])
    plt.show()

    fileName = "./trained/" + "test" if test else "final"
    model.save(fileName)
    model2 = Mlp(layers)
    model2.load(fileName)

    miss = 0
    re = 0
    for start, end in zip(testX, testY):
        prediction = model2.predict(np.array([start]))
        roundPrediction = np.array([0 if i < 0.5 else 1 for i in prediction])
        re += _cost(prediction, end)
        if np.all(roundPrediction == end):
            continue
        else:
            miss += 1
    print('test: miss', miss, "succ",  100 - (miss / max(len(testX), 1)) * 100, "%")
