from datetime import datetime

from irida_sistr_results.irida_sistr_workflow import IridaSistrWorkflow


class SampleSistrInfo(object):
    """Stores and provides access to SISTR/IRIDA information for a particular sample."""

    def __init__(self, sistr_info):
        self.sistr_info = sistr_info

    @classmethod
    def create_empty_info(cls, sample, sequencing_object=None):
        """
        Creates an empty SampleSistrInfo object (no SISTR results).
        :param sample: The sample this object refers to.
        :param sequencing_object: The sequencing object (default None).
        :return: An empty SampleSistrInfo.
        """
        data = {'sample': sample,
                'has_results': False
                }

        if sequencing_object is not None:
            data['paired_files'] = sequencing_object

        return cls(data)

    def has_sistr_results(self):
        return self.sistr_info['has_results']

    def get_sample_name(self):
        if (self.sistr_info['sample'] is not None):
            return self.sistr_info['sample']['sampleName']
        else:
            return "N/A"

    def _get_sistr(self):
        return self.sistr_info['sistr_predictions'][0]

    def get_serovar(self):
        return self._get_sistr()['serovar']

    def get_serovar_antigen(self):
        return self._get_sistr()['serovar_antigen']

    def get_serovar_cgmlst(self):
        serovar_cgmlst = self._get_sistr()['serovar_cgmlst']
        if (serovar_cgmlst is None):
            return ''
        else:
            return serovar_cgmlst

    def get_serogroup(self):
        return self._get_sistr()['serogroup']

    def get_h1(self):
        return self._get_sistr()['h1']

    def get_h2(self):
        return self._get_sistr()['h2']

    def get_o_antigen(self):
        return self._get_sistr()['o_antigen']

    def get_qc_status(self):
        return 'MISSING' if (not self.has_sistr_results()) else self._get_sistr()['qc_status']

    def get_qc_status_numerical(self):
        """Gets numerical value for QC status, used for sorting"""
        return ['MISSING', 'FAIL', 'WARNING', 'PASS'].index(self.get_qc_status())

    def get_qc_messages(self):
        return self._get_sistr()['qc_messages']

    def get_cgmlst_subspecies(self):
        return self._get_sistr()['cgmlst_subspecies']

    def get_cgmlst_genome(self):
        return self._get_sistr()['cgmlst_genome_match']

    def get_cgmlst_matching_alleles(self):
        return self._get_sistr()['cgmlst_matching_alleles']

    def get_cgmlst_matching_total_alleles(self):
        return str(self.get_cgmlst_matching_alleles()) + '/330'

    def get_cgmlst_matching_proportion(self):
        return float(self.get_cgmlst_matching_alleles()) / 330

    def get_cgmlst_sequence_type(self):
        return self._get_sistr()['cgmlst_ST']

    def get_mash_subspecies(self):
        return self._get_sistr()['mash_subspecies']

    def get_mash_serovar(self):
        return self._get_sistr()['mash_serovar']

    def get_mash_genome(self):
        return self._get_sistr()['mash_genome']

    def get_mash_distance(self):
        return self._get_sistr()['mash_distance']

    def get_submission_url(self, irida_base_url):
        submission_url = irida_base_url
        if submission_url.endswith('/'):
            submission_url += 'analysis/'
        else:
            submission_url += '/analysis/'
        submission_url += self.get_submission_identifier()

        return submission_url

    def get_submission_identifier(self):
        return self.sistr_info['submission']['identifier']

    def get_submission_workflow_id(self):
        return self.sistr_info['submission']['workflowId']

    def get_submission_workflow_version(self):
        return IridaSistrWorkflow.workflow_id_to_version(self.get_submission_workflow_id())

    def get_submission_created_date(self):
        return datetime.fromtimestamp(self.sistr_info['submission']['createdDate'] / 1000)

    def get_sample_created_date(self):
        if (self.sistr_info['sample'] is not None):
            return datetime.fromtimestamp(self.sistr_info['sample']['createdDate'] / 1000)
        else:
            return "N/A"

    def get_sample_id(self):
        if (self.sistr_info['sample'] is not None):
            return self.sistr_info['sample']['identifier']
        else:
            return "N/A"

    def get_paired_id(self):
        return self.sistr_info['paired_files'][0]['identifier']
