import os, subprocess, sys, getopt
import utils, gdv_utils
from LatexBuilder import LatexBuilder
import pr_roc_utils
import os.path
import settings

def getLinePlot(network_name, methods, enrichment_analysis_method_type, x_label, y_label,random_clustering = False, output_suffix = ''):
 

    gnuplotTemplate = file('../templates/lines.gnuplot', 'r').read()
    if not isinstance(methods,list):
        methods = [methods]
    if not isinstance(x_label,list):
        x_label = [x_label]
    if not isinstance(y_label,list):
        y_label = [y_label]
    if output_suffix != '':
        output_suffix = '_' + output_suffix

    plots_directory = settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/plots/%s_%s/' % (network_name,enrichment_analysis_method_type,'-'.join(x_label),'-'.join(y_label))


    if not os.path.exists(plots_directory):
        os.makedirs(plots_directory)
    if not os.path.exists(plots_directory + 'eps/'):
        os.makedirs(plots_directory + 'eps/')
    input_descriptions = []
    for m in methods:
        #print 'method: %s' %m
        enrichment_file = '../../%s_%s_pr_roc.txt' % (network_name, m)
        
        for x in x_label:
            for y in y_label:
                series_title = gdv_utils.getMethodName(m)
                #print 'series title: '+series_title
                #print 'xt: %s | yt: %s | series: %s ' %(x,y,series_title)
                if len(y_label)>1:
                    series_title = pr_roc_utils.get_label_title(y) + " - " + series_title
                if len(x_label)>1:
                    series_title = pr_roc_utils.get_label_title(x) + " - " + series_title
                input_descriptions.append(
                    '"%s" using %s:%s title "%s" with lines' % (enrichment_file, pr_roc_utils.get_pr_roc_file_column_number(x), pr_roc_utils.get_pr_roc_file_column_number(y),series_title)
                )
	      
		
                ## check whether random_clustering is 1. If so, include random clustering data into the graph
                if random_clustering:
                    rd=network_name + '_random'
                    rd_enrichment_file = '../../%s_%s_pr_roc.txt' % (rd, m)
                    #rd_enrichment_file='../../random-aging_dgdvs_5_2_1_pr_roc.txt'
                    rd_file_tmp=settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/%s_%s_pr_roc.txt' % (network_name,enrichment_analysis_method_type,rd, m)
                    #rd_file_tmp=settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/random-aging_dgdvs_5_2_1_pr_roc.txt' % (network_name,enrichment_analysis_method_type)
                    ## check whether random_enrichment_file exists
                    if os.path.isfile(rd_file_tmp):
                        #print 'append: %s' %rd_file_tmp

                        series_title = "Random"
                        if len(y_label)>1:
                            series_title = pr_roc_utils.get_label_title(y) + " - " + series_title
                        if len(x_label)>1:
                            series_title = pr_roc_utils.get_label_title(x) + " - " + series_title

                        x_col = pr_roc_utils.get_pr_roc_file_column_number(x,contains_std_dev=True)
                        y_col = pr_roc_utils.get_pr_roc_file_column_number(y,contains_std_dev=True)

                        if x_col != 1:
                            input_descriptions.append(
                                        '"%s" using %s:%s:%s:%s title "%s" with xyerrorbars' % (rd_enrichment_file, x_col,x_col+1, y_col, y_col+1, series_title)
                                )
                        else:
                            input_descriptions.append(
                                        '"%s" using %s:%s:%s title "%s" with yerrorbars' % (rd_enrichment_file, x_col, y_col, y_col+1, series_title)
                                )
                    else:
                        print 'random clustering file does not exist.  %s ' % (rd_file_tmp)
                        return 'empty'
   
    figure_name = network_name + '_%s_%s%s' % ('-'.join(x_label),'-'.join(y_label), output_suffix)

    #set template values
    template_values = {
        'title': network_name.replace('_','-'),
        'x_label':  ','.join([pr_roc_utils.get_label_title(x) for x in x_label]),
        'y_label': ','.join([pr_roc_utils.get_label_title(y) for y in y_label]),
        'input_description': ', '.join(input_descriptions),
        'output_file': './eps/'  + figure_name,
    }

    gnuplotFile = figure_name + '.gnuplot'

    #write gnuplot file
    open(plots_directory + gnuplotFile, mode='wb').write(gnuplotTemplate % template_values)

    #run gnuplot
    p = subprocess.Popen(['gnuplot', gnuplotFile], stdout=subprocess.PIPE, cwd = plots_directory)
    p_output = p.stdout.read()
    if p_output != '':
        print(p_output)

    return '%s_%s/' % ('-'.join(x_label),'-'.join(y_label)) + 'eps/' + figure_name + '.eps'

def getBarPlot(network_name, methods, ground_truth_type, x_label, y_label, input_file, input_file_methods,rd_clustering=False, output_suffix = ''):
    gnuplotTemplate = file('../templates/bar.gnuplot', 'r').read()
    if not isinstance(methods,list):
        methods = [methods]
    if not isinstance(x_label,list):
        x_label = [x_label]
    if not isinstance(y_label,list):
        y_label = [y_label]
    if output_suffix != '':
        output_suffix = '_' + output_suffix

    plots_directory = settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/plots/' % (network_name,ground_truth_type)
    plots_sub_directory = ('%s/' % ('-'.join(y_label))).lower()
    plots_directory += plots_sub_directory

    if not os.path.exists(plots_directory):
        os.makedirs(plots_directory)
    if not os.path.exists(plots_directory + 'eps/'):
        os.makedirs(plots_directory + 'eps/')
    input_descriptions = []
    for m in methods:
        for x in x_label:
            for y in y_label:
                series_title = gdv_utils.getMethodName(m)
                if len(y_label)>1:
                    series_title = pr_roc_utils.get_label_title(y) + " - " + series_title
                if len(x_label)>1:
                    series_title = pr_roc_utils.get_label_title(x) + " - " + series_title
                input_descriptions.append('\'%s\' using %s title "%s"' % (input_file, input_file_methods.index(m)+1, series_title))
        ## whether to generate aupr for random clustering and plot its aupr
        if rd_clustering:
            auprs=pr_roc_utils.get_AUPR(settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/%s%s_%s_pr_roc.txt' % (network_name, enrichment_analysis_method_type, network_name, '_random', m))
            print 'auprs='+str(auprs)
            if auprs != -1:
                rd_aupr_file=settings.BASE_OUTPUT_DIR + "%s/enrichment/%s/random-auprs/random-aupr-%s-%s-%s.txt" %(network_name,ground_truth_type,network_name,m,ground_truth_type)
                rd_output_file = open(rd_aupr_file,'wb')
                rd_output_file.write(str(auprs))
                rd_output_file.close()
                rd_aupr_relative="../../random-auprs/random-aupr-%s-%s-%s.txt" %(network_name,m,ground_truth_type)
                input_descriptions.append('\'%s\' using %s title "%s"' % (rd_aupr_relative, 1, "random"))
  
			
    figure_name = network_name + ('_%s%s' % ('-'.join(y_label), output_suffix)).lower()

    #set template values
    template_values = {
        'title': network_name.replace('_','-'),
        'x_label':  ','.join([pr_roc_utils.get_label_title(x) for x in x_label]),
        'y_label': ','.join([pr_roc_utils.get_label_title(y) for y in y_label]),
        'input_description': ', '.join(input_descriptions),
        'output_file': './eps/'  + figure_name,
    }

    gnuplotFile = figure_name + '.gnuplot'

    #write gnuplot file
    open(plots_directory + gnuplotFile, mode='wb').write(gnuplotTemplate % template_values)

    #run gnuplot
    p = subprocess.Popen(['gnuplot', gnuplotFile], stdout=subprocess.PIPE, cwd = plots_directory)
    p_output = p.stdout.read()
    if p_output != '':
        print(p_output)

    return plots_sub_directory + 'eps/' + figure_name + '.eps'

n_clusters = 1000
generateReport = True
convertFiguresToPng = False
run_random_clustering = True



opts, args = getopt.getopt(sys.argv[1:], "s:prh", ["subdir=","help","kmedoids_npass=","no-random-results"])
for o, a in opts:
    if o in ('-s', '--subdir'):
        inputSubDir = a  + '/'
    elif o in ('-p'):
        convertFiguresToPng = True
    elif o in ('--no-random-results'):
        run_random_clustering = False
    elif o in ('-h','--help'):
        print """Usage:
%s network_name  ground_truth_type n_clusters
-s,--subdir          Input/output subdirectory
-p                   Convert eps figures to png format (and use them for the report)
--kmedoids_npass     Number of repetions of k-medoids
--no-random-results  Do not show results for random clusterings with the same cluster sizes
-h,--help            Print this""" % sys.argv[0]
        sys.exit(0)

network_name = args[0]
ground_truth_type_list = args[1].split(',')
n_clusters_list = [int(x) for x in args[2].split(',')]

g_counter = 1
for ground_truth_type in ground_truth_type_list:
    print '%s/%s. %s' % (g_counter,len(ground_truth_type_list), ground_truth_type)
    g_counter += 1

    k_counter = 1
    for n_clusters in n_clusters_list:
        print '%s/%s. %s - %s/%s. %s clusters' % (g_counter-1,len(ground_truth_type_list), ground_truth_type,k_counter,len(n_clusters_list), n_clusters)
        k_counter += 1

        enrichment_analysis_method_type='%s_%s'% (ground_truth_type,n_clusters)
        report_name = 'report_%s_enrichment_%s' % (network_name,enrichment_analysis_method_type)


        methods = gdv_utils.getPrRocMethods(network_name,enrichment_analysis_method_type=enrichment_analysis_method_type)
        print 'Methods: ' + ', '.join(methods)
        methodsDetails =[gdv_utils.getMethodDetailsDict(m) for m in methods]


        #save AUPRs
        # create a directory for random clustering auprs.
        rd_aupr_dir=settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/random-auprs/' %(network_name,enrichment_analysis_method_type)
        if not os.path.exists(rd_aupr_dir):
            os.makedirs(rd_aupr_dir)

        aupr_filename = settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/%s_aupr_values.txt' % (network_name, enrichment_analysis_method_type, network_name)
        aupr_filename_relative = '../../%s_aupr_values.txt' % network_name #for gnuplot


        auprs = [pr_roc_utils.get_AUPR(settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/%s%s_%s_pr_roc.txt' % (network_name, enrichment_analysis_method_type, network_name, '', m)) for m in methods]
        
        #print 'size of auprs: %s || size of methods: %s' %(len(auprs),len(methods))
	
        output_file = open(aupr_filename,'wb')
        output_file.write('\t'.join([str(a) for a in auprs]))
        # for i in range(0,len(methods)):
        #     output_file.write("%s\t%s\t%s\n" % (i, methods[i], auprs[i]))
        output_file.close()


        if generateReport:
            #group plots so that to answer different questions


            #generate latex summary
            print 'Generating summary report...'

            report = LatexBuilder(
                author = 'XXX',
                title = 'Enrichment report for \'%s\' network and \'%s\' ground truth (with %s clusters)' %  (network_name.upper().replace('_','-'), ground_truth_type, n_clusters),
                graphicspath= '../../plots/'
                )

            #------------------------------------------------------------------------------------------------------

            #for the next report parts, in case there are multiple construction params, choose only one
            default_aggregated_params = 'aggregated_1'
            #default_snapshot_params = 'snapshots_1month_1'
            default_snapshot_params = ''
            #correspondence in sizes between static and dynamic graphlets
            grahplet_size_correspondence_dict = {
                '3_3': 3,
                '6_4': 4,
                '10_5': 5,
            }

            methods_temp_dict = {
                3: {},
                4: {},
                5: {}
            }


            any_relevant_methods = False

            for m in methodsDetails:
		
                mKey = '%sgdvs' % m['type']
                size_key = None
                if m['type'] in ['d','dc','dz','dcz']:
                    mKey += '_%s_%s_%s' % (m['k'], m['n'], m['delta_t'])
                    if grahplet_size_correspondence_dict.has_key('%s_%s' % (m['k'], m['n'])):
                        size_key =  grahplet_size_correspondence_dict['%s_%s' % (m['k'], m['n'])]
                else:
                    mKey += '_%s' % m['n']
                    if methods_temp_dict.has_key(m['n']):
                        size_key = m['n']
                #print 'mkey-- %s' %mKey
                if size_key is None:
                    continue
                elif not methods_temp_dict.has_key(size_key):
                    methods_temp_dict[size_key] = {}

                if methods_temp_dict[size_key].has_key(mKey):
                    methods_temp_dict[size_key][mKey].append(m['network_construction'])
                else:
                    methods_temp_dict[size_key][mKey] = [m['network_construction']]

                if len(methods_temp_dict[size_key].keys())>1:
                    any_relevant_methods = True

            #------------------------------------------------------------------------------------------------------
            print 'Part 1: Static vs dynamic...'


            if not any_relevant_methods:
                print 'No methods to compare for static vs dynamic'
            else:
                methodsForHeatmap = []
                report.addSection('Static vs dynamic',0, clearPage=True)
                #remove redundant network constructions
                for size_key in methods_temp_dict.keys():

                    for mKey in methods_temp_dict[size_key]:
                    #print 'method tmp dict: %s. | size key: %s | mkey: %s' %(methods_temp_dict[size_key][mKey],size_key,mKey)
                        if len(methods_temp_dict[size_key][mKey])>1:
                            if 'st' in mKey or 'dgdvs' in mKey or 'dcgdvs' in mKey or 'dzgdvs' in mKey or 'dczgdvs' in mKey:
                                methods_temp_dict[size_key][mKey] = [default_snapshot_params]
                            else:
                                methods_temp_dict[size_key][mKey] = [default_aggregated_params]

                    if len(methods_temp_dict[size_key])<2:
                        continue

                    report.addSection('%s-graphlets' % size_key,1)

                    method_names_sorted = sorted(methods_temp_dict[size_key], cmp = gdv_utils.compareMethodNames)
                    method_names_sorted = [(methods_temp_dict[size_key][m1][0] + '_' +  m1) if methods_temp_dict[size_key][m1][0] != '' else m1 for m1 in method_names_sorted]
                  

                    plot_list = [
                    getLinePlot(network_name, method_names_sorted, enrichment_analysis_method_type, 'r', 'p', False, output_suffix='s-vs-d-%s' % size_key),
                    getLinePlot(network_name, method_names_sorted, enrichment_analysis_method_type, 'k', 'f', False, output_suffix='s-vs-d-%s' % size_key),
                    #getBarPlot(network_name, method_names_sorted, enrichment_analysis_method_type,'Methods','AUPR', aupr_filename_relative, methods, 0, output_suffix='s-vs-d-%s' % size_key)
                    ]

                    image_caption_list = [
                        'Precision-Recall',
                        'F-score',
                        #'AUPR'
                    ]


                    report.addGroupFigure('Static vs dynamics for graphlets of size %s' % size_key,
                          plot_list,
                          image_caption_list = image_caption_list,
                          image_angle=270,
                          column_count=2
                          )

            #------------------------------------------------------------------------------------------------------
            print 'Part 2: Graphlet size...'
            methods_by_type = {}
            any_relevant_methods = False

            for m_type in ['s','st','d','dc']:
                methods_by_type[m_type] = []
                for g_size in methods_temp_dict.keys():

                    methods_by_type[m_type] += [((methods_temp_dict[g_size][m][0] + '_') if methods_temp_dict[g_size][m][0] != '' else '') + m for m in methods_temp_dict[g_size] if ((m_type+'gdvs') in m)]
                if len(methods_by_type[m_type])>1:
                    any_relevant_methods = True


            if not any_relevant_methods:
                print 'No methods to compare for the effect of graphlet size'
            else:
                report.addSection('Graphlet number of nodes',0, clearPage=True)
                for m_type in sorted(methods_by_type.keys(), cmp = gdv_utils.compareMethodTypes):

                    image_caption_list = []
                    plotList = []
                    methods_to_compare = methods_by_type[m_type]

                    if len(methods_to_compare)>1:
                        report.addSection(gdv_utils.getMethodTypeDescr(m_type),1)

                        plot_list = [
                            getLinePlot(network_name, methods_to_compare, enrichment_analysis_method_type, 'r', 'p',False, output_suffix='n-size-%s' % m_type),
                            getLinePlot(network_name, methods_to_compare, enrichment_analysis_method_type, 'k', 'f', False,output_suffix='n-size-%s' % m_type),
                            #getBarPlot(network_name, methods_to_compare, enrichment_analysis_method_type,'Methods','AUPR', aupr_filename_relative, methods, 0, output_suffix='n-size-%s' % m_type)
                        ]

                        image_caption_list = [
                            'Precision-Recall',
                            'F-score',
                            #'AUPR'
                        ]


                        report.addGroupFigure('Graphlet size for %s' % gdv_utils.getMethodTypeDescr(m_type),
                              plot_list,
                              image_caption_list = image_caption_list,
                              image_angle=270,
                              column_count=2
                              )

            #------------------------------------------------------------------------------------------------------
            print 'Part 3: Number of events...'
            any_relevant_methods = False


            methods_temp_dict = {}
            for m in methodsDetails:
                if 's' in  m['type']:
                    continue
                mKey = '%s_%s' % (m['n'], m['delta_t'])

                if not methods_temp_dict.has_key(m['type']):
                    methods_temp_dict[m['type']] = {}

                if methods_temp_dict[m['type']].has_key(mKey):
                    methods_temp_dict[m['type']][mKey].append(m['full_name'])
                    any_relevant_methods = True
                else:
                    methods_temp_dict[m['type']][mKey] = [m['full_name']]

            #choose one network construction (if there are more than one)
            for m_type in methods_temp_dict:
                for mKey in methods_temp_dict[m_type]:
                    constr_parms = set()

                    for m in methods_temp_dict[m_type][mKey]:
                        m_temp  = gdv_utils.getMethodDetailsDict(m)
                        constr_parms.add(m_temp['network_construction'])
                    if len(constr_parms)>1:
                        m_list_temp  = list(methods_temp_dict[m_type][mKey])
                        for m in m_list_temp:
                            m_temp = gdv_utils.getMethodDetailsDict(m)
                            if default_snapshot_params != m_temp['network_construction']:
                                methods_temp_dict[m_type][mKey].remove(m)

            if not any_relevant_methods:
                print 'No methods to compare for the effect of graphlet size'
            else:
                report.addSection('Graphlet number of events',0, clearPage=True)
                for m_type in sorted(methods_temp_dict.keys(), cmp = gdv_utils.compareMethodTypes):

                    if len(methods_temp_dict[m_type]) == 0:
                        continue

                    report.addSection(gdv_utils.getMethodTypeDescr(m_type),1)



                    for mKey in sorted(methods_temp_dict[m_type]):
                        if len(methods_temp_dict[m_type][mKey])<2:
                            continue

                        image_caption_list = []
                        plotList = []
                        temp_methods_list = sorted(methods_temp_dict[m_type][mKey], gdv_utils.compareMethodNames)
                        #print ', '.join(temp_methods_list)

                        plot_list = [
                            getLinePlot(network_name, temp_methods_list, enrichment_analysis_method_type, 'r', 'p', False, output_suffix='k-size-%s-%s' % (m_type,mKey.split('_')[0])),
                            getLinePlot(network_name, temp_methods_list, enrichment_analysis_method_type, 'k', 'f', False, output_suffix='k-size-%s-%s' % (m_type,mKey.split('_')[0])),
                            #getBarPlot(network_name, temp_methods_list, enrichment_analysis_method_type,'Methods','AUPR', aupr_filename_relative, methods, 0, output_suffix='k-size-%s-%s' % (m_type,mKey.split('_')[0]))
                        ]

                        image_caption_list = [
                            'Precision-Recall',
                            'F-score',
                            #'AUPR'
                        ]


                        report.addGroupFigure('Comparison for %s (n=%s)' % (gdv_utils.getMethodTypeDescr(m_type),mKey.split('_')[0]),
                              plot_list,
                              image_caption_list = image_caption_list,
                              image_angle=270,
                              column_count=2
                              )


            print 'Part 4: Individual (Precision/Recall vs k)'
            
            if len(methods) == 0:
                print 'No methods for analysis'
            else:
                report.addSection('Precision/Recall vs k',0, clearPage=True)
                methods_temp_dict = {}
                for m in methodsDetails:
                    if not methods_temp_dict.has_key(m['type']):
                        methods_temp_dict[m['type']] = []
                    methods_temp_dict[m['type']].append(m['full_name'])

                for m_type in sorted(methods_temp_dict.keys(), cmp = gdv_utils.compareMethodTypes):
                    if len(methods_temp_dict[m_type])==0:
                        continue

                    report.addSection(gdv_utils.getMethodTypeDescr(m_type),1)
                    plot_list = []
                    image_caption_list = []
                    for m in sorted(list(set(methods_temp_dict[m_type]))):
                        plot_list.append(getLinePlot(network_name, m, enrichment_analysis_method_type, 'k', ['p','r'],False, m))
                        image_caption_list.append(gdv_utils.getMethodName(m))

                    report.addGroupFigure('Results for %s' % (gdv_utils.getMethodTypeDescr(m_type)),
                                          plot_list,
                                          image_caption_list = image_caption_list,
                                          image_angle=270,
                                          column_count=3
                                          )
            if run_random_clustering:
                print 'Part 5: Method Vs. Random clusterings'
                report.addSection('Method vs Random Clusterings',0, clearPage=True)
                i=0
                ##

                methods_temp_dict = {}
                for m in methodsDetails:
                    if not methods_temp_dict.has_key(m['type']):
                        methods_temp_dict[m['type']] = []
                    methods_temp_dict[m['type']].append(m['full_name'])
                for m_type in sorted(methods_temp_dict.keys(), cmp = gdv_utils.compareMethodTypes):
                    if len(methods_temp_dict[m_type])==0:
                        continue

                    report.addSection(gdv_utils.getMethodTypeDescr(m_type),1)

                    image_caption_list = []
                    for m in sorted(methods_temp_dict[m_type], cmp = gdv_utils.compareMethodNames):
                        plot_list = [
                          getLinePlot(network_name, m, enrichment_analysis_method_type, 'r', 'p', True, output_suffix='random-%s' % (m)),
                          getLinePlot(network_name, m, enrichment_analysis_method_type, 'k', 'f', True, output_suffix='random-%s' % (m)),
                          getLinePlot(network_name, m, enrichment_analysis_method_type, 'k', ['p','r'],True, output_suffix='random-%s' % (m)),
                          #getBarPlot(network_name, mm, enrichment_analysis_method_type,'Methods','AUPR', aupr_filename_relative, methods,1, output_suffix='random-%s' % (mm))
                        ]
                        ## if the random clustering result for a given network method does not exist, do not plot
                        if plot_list[0] == 'empty':
                            print 'empty'
                            continue

                        image_caption_list = [
                            'Precision-Recall',
                            'F-score',
                            'Precision/Recall vs k',
                       ]

                        report.addGroupFigure('%s vs Random' % (gdv_utils.getMethodName(m)),
                            plot_list,
                            image_caption_list = image_caption_list,
                            image_angle=270,
                            column_count=3
                        )

        report.compile(settings.BASE_OUTPUT_DIR + '%s/enrichment/%s/report/' % (network_name,enrichment_analysis_method_type), report_name)
