#
#  Copyright (C) 2016 STFC Rutherford Appleton Laboratory, UK.
#
#  Author: David Waterman
#  Acknowledgements: based on code by Graeme Winter and Martin Noble.
#

import os
from CCP4ReportParser import Report
import aimless_pipe_report
import json

class xia2_dials_report(Report):

    TASKNAME = 'xia2_dials'
    RUNNING = True

    def __init__(self, xmlnode=None,jobInfo={}, **kw):
        Report. __init__(self,xmlnode=xmlnode,jobInfo=jobInfo, **kw)
        job_stat = kw.get('jobStatus', None)
        if job_stat is not None and job_stat.lower() == 'nooutput':
            return
        elif job_stat is not None and job_stat.lower() == 'running':
            self.runningReport(parent=self)
        else:
            self.defaultReport(parent=self)

    def runningReport(self, parent=None):
        if parent is None: parent = self
        xia2SummaryFold=parent.addFold(label='xia2 text',
                                       initiallyOpen=True)
        xia2TxtNode = self.xmlnode.xpath0('Xia2Txt')
        if xia2TxtNode is not None:
            xia2SummaryFold.addPre(text=xia2TxtNode.text)

    def defaultReport(self, parent=None):
        if parent is None: parent = self
        self.addDiv(style='clear:both;') # gives space for the title
        xia2TxtNode = self.xmlnode.xpath0('Xia2Txt')
        xia2ErrorNode = self.xmlnode.xpath0('Xia2Error')
        xia2html = os.path.normpath(os.path.join(self.jobInfo['fileroot'],
                                                 'xia2.html'))
        if os.path.exists(xia2html):
            xia2HtmlFold=parent.addFold(label='xia2 report',
                                        initiallyOpen=True)
            xia2HtmlFold.append('<span style="font-size:110%">Click on the '
                'following link to display the xia2.html report in a '
                'browser </span>')
            xia2HtmlFold.append(
                '<a href="{0}">Open Results</a>'.format(xia2html))
        if xia2ErrorNode is not None:
            parent.addText(style='font-size:125%;color:red;',
                           text='xia2 exited with an error')
            if xia2TxtNode is not None:
                parent.addPre(text=xia2TxtNode.text)
            parent.addPre(text=xia2ErrorNode.text)
        elif xia2TxtNode is not None:
            xia2SummaryFold=parent.addFold(label='xia2 Text',
                                           initiallyOpen=False)
            xia2SummaryFold.addPre(text=xia2TxtNode.text)

        # xia2 summary (a table gleaned from xia2.json)
        self.xia2Summaries(parent=parent)

        # Now include the Aimless pipeline report
        defaultScalePath = os.path.normpath(os.path.join(
            self.jobInfo['fileroot'],'DEFAULT','scale'))
        spoofedJobInfo = {'fileroot':defaultScalePath}
        apReport = aimless_pipe_report.aimless_pipe_report(
            xmlnode=self.xmlnode, jobStatus='nooutput', jobInfo=spoofedJobInfo)
        apReport.defaultReport(parent=parent)

        return

    def xia2Summaries(self, parent=None):

        if parent is None: parent=self
        runSummaryFold = self.addFold(label="xia2 run summaries",
                                      initiallyOpen=True)
        runTable = runSummaryFold.addTable(title="Summary table",
                                           transpose=True)

        names = []
        spaceGroups = []
        cells = []

        from collections import namedtuple
        Stat = namedtuple('Stat', ['title', 'fmt'])
        statistics = {'I/sigma':Stat('I/sigI','%.2f'),
                      'Completeness':Stat('Completeness', '%.1f'),
                      'Rpim(I)':Stat('Rpim (pooled Friedels)', '%.3f'),
                      'Multiplicity':Stat('Multiplicity', '%.1f'),
                      'Rpim(I+/-)':Stat('Rpim (separate Friedels)', '%.3f'),
                      'Rmeas(I)':Stat('Rmeas (pooled Friedels)', '%.3f'),
                      'Low resolution limit':Stat('Lower res.', '%.2f'),
                      'High resolution limit':Stat('High res.', '%.2f'),
                      'Total observations':Stat('#Obs', '%d'),
                      'Anomalous multiplicity':Stat('Anom. Mult.', '%.1f'),
                      'Rmerge(I+/-)':Stat('Rmerge', '%.3f'),
                      'Anomalous completeness':Stat('Anom Compl', '%.1f'),
                      'Total unique':Stat('#Unique', '%d')}
        orderedKeys = ['Low resolution limit',
                       'High resolution limit',
                       'I/sigma',
                       'Completeness',
                       'Anomalous completeness',
                       'Rmerge(I+/-)',
                       'Rpim(I+/-)',
                       'Rpim(I)',
                       'Rmeas(I)',
                       'Multiplicity',
                       'Anomalous multiplicity',
                       'Total observations',
                       'Total unique']
        statisticDict = {}
        for statistic in statistics:
            statisticDict[statistic] = []

        # Loop over data taken from xia2.json
        for runNode in self.xmlnode.xpath('//Xia2Json'):
            dic = json.loads(runNode.text)
            names.append(dic.get('_name'))
            crystals = dic['_crystals']
            if len(crystals) > 1: return # don't cope with > 1 crystal here

            k = dic['_crystals'].keys()[0]
            dat = dic['_crystals'][k]

            k = dat['_scaler']['_scalr_statistics'].keys()[0]
            stat = dat['_scaler']['_scalr_statistics'][k]

            spaceGroups.append(",".join((dat['_scaler']['_scalr_likely_spacegroups'])))
            cell = dat['_scaler']['_scalr_cell']
            cells.append((', '.join(["{:.2f}"] * 6)).format(*cell))

            for key in statistics:
                try:
                    fmt = statistics[key].fmt
                    overallValue = fmt % stat[key][0]
                    outerValue = fmt % stat[key][2]
                    statisticDict[key].append(
                        overallValue+' ('+outerValue+')')
                except:
                    statisticDict[statistic].append(
                        'Not known')

        runTable.addData(title='Run name', data=names)
        runTable.addData(title='Space group', data=spaceGroups)
        runTable.addData(title='Unit cell', data=cells)
        for key in orderedKeys:
            runTable.addData(title=statistics[key].title,
                             data=statisticDict[key])
