import numpy as np
import math
import csv
import networkx as nx
from networkx.readwrite import json_graph
from numpy import genfromtxt
import json
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.metrics import pairwise_distances
from deal_DataGYC import dealdata4
from graph2vec import subgraph
from parsor import parameter_parser
import os

def deal(name, l, window, hour):
    arr = genfromtxt(name, delimiter = '\t', dtype = 'int')
    ma = arr[:, [0, 1, 2]]
    minTime = ma[0][0]
    maxTime = ma[0][0]
    for i in range(len(ma)):  # 求上下限时间
        time = ma[i][0]
        if time < minTime:
            minTime = time
        if time > maxTime:
            maxTime = time
    attr = {}
    num = -1
    for i in range(len(ma)):  # id从0-max
        start = ma[i][1]
        end = ma[i][2]
        if start not in attr:
            num += 1
            attr[start] = num
        if end not in attr:
            num += 1
            attr[end] = num
        ma[i][1] = attr[start]
        ma[i][2] = attr[end]
    maTime = {}
    num += 1
    for i in range(len(ma)):  # 按每分钟构建全图矩阵
        line = ma[i]
        time = math.floor((line[0] - minTime) / 60)
        if time not in maTime:
            maTime[time] = np.zeros((num, num), dtype = 'int')
        maTime[time][ma[i][1]][ma[i][2]] = 1
        maTime[time][ma[i][2]][ma[i][1]] = 1

    index = 0
    # f = open('graph', 'w')
    f1 = open('vector'+str(hour), 'w')
    # f2 = open('degree', 'w')
    employee_writer = csv.writer(f1, delimiter = ',', quotechar = '"', quoting = csv.QUOTE_MINIMAL)
    # employee_degree = csv.writer(f2, delimiter = ',', quotechar = '"', quoting = csv.QUOTE_MINIMAL)
    result = []
    ma_arr = []
    while (1):
        start = index * window
        end = start + l
        if end * 60 + minTime > maxTime:
            break
        index += 1
        r = np.zeros((num, num), dtype = 'int')
        for i in range(start, end):
            if i in maTime:
                r += maTime[i]
        res = []
        for i in r:
            res.extend(i)
        employee_writer.writerow(res)
        ma_arr.append(r)
        G = nx.from_numpy_matrix(r)
        g = json_graph.node_link_data(G)
        g['time']=start #   add by gyc
        # degree = G.degree().values()
        # employee_degree.writerow(degree)
        result.append(g)
        print(start, end)
    grapha = []
    graphb = []
    de = int(hour * 60 / 6)
    for i in range(len(ma_arr) - de):  # 这里是构建差图
        a = ma_arr[i + de]
        b = ma_arr[de]
        G = nx.from_numpy_matrix(a - (a & b))
        g = json_graph.node_link_data(G)
        g['time']=(i+de,i)
        grapha.append(g)
        G = nx.from_numpy_matrix(b - (a & b))
        g = json_graph.node_link_data(G)
        g['time']=(i,i+de)
        graphb.append(g)
    f3 = open('delta_graph_a'+str(hour).replace('.','_'), 'w')
    f4 = open('delta_graph_b'+str(hour).replace('.','_'), 'w')
    json.dump(grapha, f3)
    json.dump(graphb, f4)
    if(os.path.exists('graph')==False):
        f = open('graph', 'w')
        json.dump(result, f)
        f.close()
    f1.close()
    # f2.close()
    f3.close()
    f4.close()
    print(num, index)


# return result_vector

def read(name, delta, hour):
    X = []
    with open(name, 'r') as csvfile:
        csvreader = csv.reader(csvfile, delimiter = ",")
        deltas = []
        for raw_line in csvreader:
            if len(raw_line) > 0:
                deltas.append(raw_line)
        print(len(deltas))
        X = np.array(deltas, dtype = 'float')
        if delta:
            r = []
            for i in range(len(X) - hour):
                # r.append(np.concatenate((Y[i + 1] - Y[i], X[i + 1] - X[i])))
                a = X[i + hour]
                b = X[i]
                # r.append(np.concatenate((a - (a & b), (b - (a & b) * -1))))
                r.append(a - b)
            X = np.array(r)
            #toDo
            np.savetxt(name+str(hour).replace('.','_')+'_delta.csv',X,fmt='%.17f',delimiter=',')
        print('read finish', name)
    return X


def reduce(namea, method, delta, dis, file, hour, nameb = ""):
    X = read(namea, delta, hour)
    if nameb != "":
        Y = read(nameb, delta, hour)
        r = []
        for i in range(len(X)):
            a = X[i]
            b = Y[i] * -1
            # first=[i+10]
            # second=[i]
            # r.append(np.concatenate((first,second,a, b)))
            r.append(np.concatenate((a, b)))
        X = np.array(r)
        #toDo
        np.savetxt(namea.replace('.','_')+'_DGE.csv',X,fmt='%.17f',delimiter=',')

    if method == 'tsne':
        if dis == 'cosine':
            distance_matrix = pairwise_distances(X, X, metric = 'cosine', n_jobs = -1)
            print('distance_matrix finish')
            X_embedded = TSNE(n_components = 2, perplexity = 20, metric = "precomputed").fit_transform(
                distance_matrix)
        else:
            X_embedded = TSNE(n_components = 2, perplexity = 20).fit_transform(X)
        if not os.path.exists("./projection/data/"):
            os.mkdir("./projection/data/")
        count=0
        new_embedded=[]
        for note in X_embedded:
            first=[count+10]
            second=[count]
            if nameb=='' and delta==False:
                new_note=np.concatenate((second,note))
            else:
                new_note=np.concatenate((first,second,note))
            new_embedded.append(new_note)
            count=count+1
        np.savetxt("./projection/data/" + file, new_embedded, fmt='%.17f',delimiter = ",")
    elif method == 'pca':
        X_embedded = PCA(n_components = 2).fit_transform(X)
        count=0
        new_embedded=[]
        for note in X_embedded:
            first=[count+10]
            second=[count]
            if nameb=='' and delta==False:
                new_note=np.concatenate((second,note))
            else:
                new_note=np.concatenate((first,second,note))
            new_embedded.append(new_note)
            count=count+1
        np.savetxt("./projection/data/" + file, new_embedded,fmt='%.17f', delimiter = ",")

#得到图的投影(json格式，用于和前端的直接交互)
def getGraphProjection(type,hour,projectiontype):
    if type=='origin':
        filename = 'projection/data/graph2vec_' + projectiontype + '_' + type
    else:
        filename='projection/data/graph2vec_'+projectiontype+'_'+type+'_'+str(hour).replace('.','_')
    if os.path.exists(filename):
        embeddings=np.loadtxt(filename,delimiter=',')
        json_embedding=dict()
        if(type=="origin"):
            for embedding in embeddings:
                json_embedding[int(embedding[0])]=embedding[-2]
        else:
            for embedding in embeddings:
                key = str(tuple(embedding[0:2]))
                json_embedding[key]=embedding[2:4].tolist()
        print(json_embedding)
        return json.dumps(json_embedding)
    else:
        calculateGraphProjectin(type,hour,projectiontype)
        return 'Try Again!'


#计算投影（同时顺带计算了embedding）
def calculateGraphProjectin(type,hour,projectiontype):
    embeddingfilegraph = 'graph_graph2vec.csv'
    embeddingfiledelta_a = 'delta_graph_a' + str(hour).replace('.', '_') + '_graph2vec.csv'
    embeddingfiledelta_b = 'delta_graph_b' + str(hour).replace('.', '_') + '_graph2vec.csv'
    if type == 'orgin':
        if os.path.exists(embeddingfilegraph):
            reduce(embeddingfilegraph, "", projectiontype, 'cosine', False, 'graph2vec_'+projectiontype+'_orign')
    elif type == 'delta':
        if os.path.exists(embeddingfilegraph):
            reduce(embeddingfilegraph, "", projectiontype, 'cosine', True, 'graph2vec_tsne_delta_' + str(hour).replace('.','_'))
    elif type=='DGE':
        if os.path.exists(embeddingfiledelta_a):
            reduce(embeddingfiledelta_a, embeddingfiledelta_b, projectiontype, 'cosine', False, 'graph2vec_tsne_DGE_' + str(hour).replace(
            '.', '_'))



# 得到embedding(json格式)，用于和前端的直接交互
def getEmbedding(type,hour):
    if type=='origin':
        filename = 'graph_graph2vec.csv'
    else:
        filename='delta_graph_a'+str(hour).replace('.','_')+'_graph2vec.csv'
    if os.path.exists(filename):
        de = int(hour * 60 / 6)
        i=0
        embeddings=np.loadtxt(filename,delimiter=',')
        json_embedding=dict()
        if type=="origin":
            for embedding in embeddings:
                json_embedding[i]=embedding
                i+=1
        elif type=='delta_a':
            for embedding in embeddings:
                key = str(tuple(i+de,i))
                json_embedding[key]=embedding.tolist()
                i+=1
        elif type=='delta_b':
            for embedding in embeddings:
                key = str(tuple(i,i+de))
                json_embedding[key]=embedding.tolist()
                i+=1
        print(json_embedding)
        return json.dumps(json_embedding)
    else:
        calculateEmbedding(type,hour)
        return getEmbedding(type,hour)



#计算embedding
def calculateEmbedding(type,hour):
    window = 6
    l = 60
    deal('highschool_2012.csv', l, window, hour)
    dealdata4('delta_graph_a'+str(hour).replace('.','_'))
    dealdata4('delta_graph_b'+str(hour).replace('.','_'))
    arguments = parameter_parser()
    embeddingfiledelta_a = 'delta_graph_a' + str(hour).replace('.', '_') + '_graph2vec.csv'
    embeddingfiledelta_b = 'delta_graph_b' + str(hour).replace('.', '_') + '_graph2vec.csv'
    #开始处理图3
    arguments.input_path ='dataset/delta_graph_a'+str(hour)+'/'
    arguments.output_path=embeddingfiledelta_a
    subgraph(arguments)
    arguments.output_path=embeddingfiledelta_b
    arguments.input_path ='dataset/delta_graph_b'+str(hour)+'/'
    subgraph(arguments)





if __name__ == '__main__':
    name = 'highschool_2012.csv'
    # vector = 'nci1.csv'
    r = []
    # r.append(['graph2vec.csv', "", 'tsne', 'cosine', False, 'graph2vec_tsne_orign'])
    # r.append(['graph2vec.csv', "", 'pca', 'cosine', False, 'graph2vec_pca_orign'])
    # r.append(['graph2vec.csv', "", 'pca', 'cosine', True, 'graph2vec_pca_delta'])
    # r.append(['graph2vec.csv', "", 'tsne', 'cosine', True, 'graph2vec_tsne_delt'])
    # r.append(['delta_a_graph2vec.csv', "delta_b_graph2vec.csv", 'tsne', 'cosine', False, 'graph2vec_tsne_GEM'])
    # r.append(['delta_a_graph2vec.csv', "delta_b_graph2vec.csv", 'pca', 'cosine', False, 'graph2vec_pca_Gem'])

    # r.append(['graph2vec_id.csv', "", 'tsne', 'cosine', False, 'graph2vec_id_tsne_orign'])
    # r.append(['graph2vec_id.csv', "", 'pca', 'cosine', False, 'graph2vec_id_pca_orign'])
    # r.append(['graph2vec_id.csv', "", 'pca', 'cosine', True, 'graph2vec_id_pca_delta'])
    # r.append(['graph2vec_id.csv', "", 'tsne', 'cosine', True, 'graph2vec_id_tsne_delta'])
    # r.append(['delta_a_graph2vec_id.csv', "delta_b_graph2vec_id.csv", 'tsne', 'cosine', False, 'graph2vec_id_tsne_GEM'])
    # r.append(['delta_a_graph2vec_id.csv', "delta_b_graph2vec_id.csv", 'pca', 'cosine', False, 'graph2vec_id_pca_Gem'])

    # r.append(['graphlets.csv', "", 'tsne', 'cosine', False, 'graphlets_tsne_orign'])
    # r.append(['graphlets.csv', "", 'pca', 'cosine', False, 'graphlets_pca_orign'])
    # r.append(['graphlets.csv', "", 'tsne', 'cosine', True, 'graphlets_tsne_delta'])
    # r.append(['graphlets.csv', "", 'pca', 'cosine', True, 'graphlets_pca_delta'])
    # r.append(['delta_a_graphlets.csv', "delta_b_graphlets.csv", 'tsne', 'cosine', False, 'graphlets_tsne_GEM'])
    # r.append(['delta_a_graphlets.csv', "delta_b_graphlets.csv", 'pca', 'cosine', False, 'graphlets_pca_GEM'])

    # r.append(['delta_a_graph2vec_id.csv', "delta_b_graph2vec_id.csv", 'tsne', 'cosine', False, 'graph2vec_tsne_GEM_id'])
    # r.append(['graph2vec_id.csv', "", 'tsne', 'cosine', False, 'test'])

    l = 60 # 这里是一个图应该表示多久，一小时
    window = 6 #这里是重叠度，0-60 下一帧就是 6-66
    #hour = 0.1 # 这里是做差的时候是相差多久，现在相邻时间是6分钟，即0.1小时
    #deal(name,l,window,hour)#这个函数是用来生成graph的
    # time_interval=[0.1,0.5]
    # time_interval.extend(np.arange(1.0,25.0,1.0).tolist())
    # for hour in time_interval:
    #     deal('highschool_2012.csv', l, window, hour)
    #     print(hour)
    # print('deal finished!')
    # deal('highschool_2012.csv', l, window, 0.1)
    # deal('highschool_2012.csv', l, window, 1.0)
    # deal('highschool_2012.csv', l, window, 12.0)
    # deal('highschool_2012.csv', l, window, 24.0)
    #
    time_interval=[12.0,24.0]
    for hour in time_interval:
        print('------------------------time_interval----------------------------')
        print('hour： '+str(hour))
        # #原始的图只要处理一次就可以了
        # if not os.path.exists('graph'):
        #     dealdata4('graph')
        # dealdata4('delta_graph_a'+str(hour).replace('.','_'))
        # dealdata4('delta_graph_b'+str(hour).replace('.','_'))
        # arguments = parameter_parser()
        embeddingfilegraph='graph_graphlets.csv'
        embeddingfiledelta_a='delta_graph_a'+str(hour).replace('.','_')+'_graphlets.csv'
        embeddingfiledelta_b='delta_graph_b'+str(hour).replace('.','_')+'_graphlets.csv'
        r = []
        # #开始处理图3
        # arguments.input_path ='dataset/delta_graph_a'+str(hour)+'/'
        # arguments.output_path=embeddingfiledelta_a
        # subgraph(arguments)
        # arguments.output_path=embeddingfiledelta_b
        # arguments.input_path ='dataset/delta_graph_b'+str(hour)+'/'
        # subgraph(arguments)

        if(os.path.exists('projection/data/graph2vec_tsne_orign')==False):
            # arguments.input_path = 'dataset/graph/'
            # arguments.output_path = embeddingfilegraph
            # subgraph(arguments)
            # # False表示的是原图
            r.append([embeddingfilegraph, "", 'tsne', 'cosine', False, 'graph2vec_tsne_orign'])
            r.append([embeddingfilegraph, "", 'pca', 'cosine', False, 'graph2vec_pca_orign'])
        r.append([embeddingfilegraph, "", 'pca', 'cosine', True, 'graph2vec_pca_delta_' + str(hour).replace('.','_')])
        r.append([embeddingfilegraph, "", 'tsne', 'cosine', True, 'graph2vec_tsne_delta_' + str(hour).replace('.','_')])
        r.append([embeddingfiledelta_a, embeddingfiledelta_b, 'tsne', 'cosine', False, 'graph2vec_tsne_DGE_'+str(hour).replace('.','_')])
        r.append([embeddingfiledelta_a, embeddingfiledelta_b, 'pca', 'cosine', False, 'graph2vec_pca_DGE_'+str(hour).replace('.','_')])
        for t in r:
            vectora = t[0]
            vectorb = t[1]
            method = t[2]
            dis = t[3]
            delta = t[4]  # 用embedding的差
            file = t[5]
            reduce(vectora, method, delta, dis, file, int(l* hour/window), vectorb)
            print(file)


