import json

class HyperGraph:

    cluster_labels = []
    dest_cluster_labels = []
    label_values = []

    def __init__(self):
        pass

    def classify(self):
        df_nodes = self.load_values()

        ret_val = self.init(df_nodes)
        nodeIds = ret_val['nodeIds']
        clusterlabels = ret_val['clusterlabels']
        destIds = ret_val['destIds']
        
        clusterlabels = self.classify_input(nodeIds, clusterlabels)

        labelvals = self.calc_cluster_num(clusterlabels)

        cluster = self.cluster_with_labels(nodeIds, clusterlabels, labelvals)

        cluster = self.remove_duplicates(cluster)

        destclusterlabel = self.cluster_dest_ids(labelvals, cluster, destIds)

        self.cluster_labels = clusterlabels
        self.dest_cluster_labels = destclusterlabel
        self.labelvals = labelvals

    def load_values(self):
        with open("mult_in_out_large.json", "r") as json_file:
            df_nodes = json.load(json_file)

        return df_nodes

    def init(self, df_nodes):
        nodeIds = []
        clusterlabels = []
        destIds = []

        for row in df_nodes:
            for j in range(len(row['TransactionFrom'])):
                print("   Input Ids:  ", row['TransactionFrom'][j])
            nodeIds.append(row['TransactionFrom'])
            print("This is nodes:  ", nodeIds)

        for row in df_nodes:
            destIds.append(row['TransactionTo'])

        for row in range(len(nodeIds)):
            print(nodeIds[row])

        print("Finish InputIDs")
        i = 0
        for row in range(len(nodeIds)):
            clusterlabels.append(row)
            i += 1

        print(i)
        return {'nodeIds': nodeIds,
                'clusterlabels': clusterlabels,
                'destIds': destIds}

    def classify_input(self, nodeIds, clusterlabels):
        """" classifying Inputs"""
        """" Labaling inputs"""
        for row in range(len(nodeIds)):

            for rown in range(len(nodeIds[row])):

                for row1 in range(len(nodeIds)):
                    for rown1 in range(len(nodeIds[row1])):
                        if(nodeIds[row][rown]==nodeIds[row1][rown1]):
                            # print("row:  ",row,"row1:  ",row1)
                            if(row < row1):
                                for row2 in clusterlabels:
                                    if( clusterlabels[row1]== clusterlabels[row2]):
                                        clusterlabels[row2]=clusterlabels[row]
                                clusterlabels[row1] = clusterlabels[row]

                            else:
                                for row2 in clusterlabels:
                                    if (clusterlabels[row] == clusterlabels[row2]):
                                        clusterlabels[row2] = clusterlabels[row1]
                                clusterlabels[row] = clusterlabels[row1]

        print(clusterlabels)
        print("cluster labels:", len(clusterlabels))
        print("NodeIDs:   ", len(nodeIds))
        return clusterlabels

    def calc_cluster_num(self, clusterlabels):
        """" Calculating the number of clusters"""
        labelvals = []

        labelvals.append(clusterlabels[0])
        for row in range(len(clusterlabels)):
            flag = True
            for row1 in range(len(labelvals)):
                if(clusterlabels[row]== labelvals[row1]):
                    flag = False

            if (flag):
                labelvals.append(clusterlabels[row])

        print("label values (source Ids in the network):  ", labelvals, " and the number of clusters is: ", len(labelvals))

        return labelvals

    def cluster_with_labels(self, nodeIds, clusterlabels, labelvals):
        """" clustering Ids according to their labels"""
        cluster = []

        for row in range(len(labelvals)):
            cluster.append([])
            for row3 in range(len(nodeIds)):
                if (labelvals[row] == clusterlabels[row3]):
                    cluster[row].extend(nodeIds[row3])
        print("clusters:   ", cluster)

        return cluster

    def remove_duplicates(self, cluster):
        """ Removing duplicating items in cluster"""

        flag = True
        while(flag):
            for row in range(len(cluster)):

                flag= False
                for row1 in range(len(cluster[row])):
                    flag= False
                    for row2 in range (len(cluster[row])):
                        if(row1 != row2):
                            if(cluster[row][row1] == cluster[row][row2]):
                                del cluster[row][row2]
                                flag=True
                                break
                    if(flag):
                        break
                if(flag):
                    break

        print("cluster:", cluster)
        
        return cluster

    def cluster_dest_ids(self, labelvals, cluster, destIds):
        """" Clustering  Destination Ids """
        destclusterlabel = []

        for row in range(len(destIds)):
            destclusterlabel.append([])
            for row2 in range(len(destIds[row])):
                flag = True
                for rownum in range(len(labelvals)):
                    for row1 in range(len(cluster[rownum])):

                        if(destIds[row][row2]== cluster[rownum][row1]):
                            destclusterlabel[row].append(labelvals[rownum])
                            flag = False
                if(flag):
                    destclusterlabel.append(destIds[row][row2])

        print("destination labels (destination Ids):  ", destclusterlabel)

        return destclusterlabel