<commit_before>"""
Copyright (C) 2014  Genome Research Ltd.

Author: <NAME> <<EMAIL>>

This program is part of metadata-check.

metadata-check is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

This file has been created on Nov 3, 2014.
"""

import re
import typing

from mcheck.header_parser.sam.file_header import SAMFileHeader
from mcheck.com import wrappers


class SAMFileHeaderParser:
    """
        Abstract class to be inherited by all the classes that contain header parsing functionality.
    """
    @classmethod
    def parse(cls, header_as_text: str):
        """
        Receives a BAM header as text (string) and parses it.
        It returns a SAMFileHeader - containing the tags as lists of strings,
        where each string is a line from the header.
        According to the docs, a SAM header has:
            - RG = REGION tag
            - PG = PROGRAM tag
            - HD = HEAD tag
            - SQ = SEQUENCE tag
        Parameters
        ----------
        header_as_text : str
            Header as text (string)
        Returns
        -------
        header: SAMFileHeader
        """
        rg_list, sq_list, pg_list, hd_list = [], [], [], []
        lines = header_as_text.split('\n')
        for line in lines:
            if line.startswith('@SQ'):
                sq_list.append(line)
            elif line.startswith('@HD'):
                hd_list.append(line)
            elif line.startswith('@PG'):
                pg_list.append(line)
            elif line.startswith('@RG'):
                rg_list.append(line)
        return SAMFileHeader(rg_tag=rg_list, pg_tag=pg_list, hd_tag=hd_list, sq_tag=sq_list)


class SAMFileRGTagParser:

    def parse(self, tags):
        seq_center_list, seq_dates, lanelets, platforms, libraries, samples, platform_units = [], [], [], [], [], [], []
        for read_grp in tags:
            if 'CN' in read_grp:
                seq_center_list.append(read_grp['CN'])
            if 'DT' in read_grp:
                seq_dates.append(read_grp['DT'])
            if 'SM' in read_grp:
                samples.append(read_grp['SM'])
            if 'LB' in read_grp:
                libraries.append(read_grp['LB'])
            if 'PU' in read_grp:
                platform_units.append(read_grp['PU'])
            if 'PL' in read_grp:
                platforms.append(read_grp['PL'])

        return SAMFileHeader.RGTag(
            seq_centers=[_f for _f in list(set(seq_center_list)) if _f],
            seq_dates=[_f for _f in list(set(seq_dates)) if _f],
            lanelets=[_f for _f in list(set(lanelets)) if _f],
            platforms=[_f for _f in list(set(platforms)) if _f],
            libraries=[_f for _f in list(set(libraries)) if _f],
            samples=[_f for _f in list(set(samples)) if _f],
            platform_units=[_f for _f in list(set(platform_units)) if _f]
        )


class SangerSeqSAMFileRGTagParser:

#    class RGTagParser:
    LANELET_NAME_REGEX = '[0-9]{4}_[0-9]{1}#[0-9]{1,2}'
    LANE_NAME_REGEX = '[0-9]{4}_[0-9]{1}'

    @classmethod
    def parse(cls, tags: typing.Sequence):
        """ This method parses all the RGs (ReadGroup) in the list received as parameter
        and returns a BAMHeaderRG containing the information found there.
        Parameters
        ----------
        rgs_list: list<commit_msg>Fixed bugs in parser and added a new method<commit_after>"""
Copyright (C) 2014  Genome Research Ltd.

Author: <NAME> <<EMAIL>>

This program is part of metadata-check.

metadata-check is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

This file has been created on Nov 3, 2014.
"""

import re
import typing

from mcheck.header_parser.sam.header import SAMFileHeader
from mcheck.com import wrappers


class SAMFileHeaderParser:
    """
        Abstract class to be inherited by all the classes that contain header parsing functionality.
    """
    @classmethod
    def parse(cls, header_as_text: str):
        """
        Receives a BAM header as text (string) and parses it.
        It returns a SAMFileHeader - containing the tags as lists of strings,
        where each string is a line from the header.
        According to the docs, a SAM header has:
            - RG = REGION tag
            - PG = PROGRAM tag
            - HD = HEAD tag
            - SQ = SEQUENCE tag
        Parameters
        ----------
        header_as_text : str
            Header as text (string)
        Returns
        -------
        header: SAMFileHeader
        """
        rg_list, sq_list, pg_list, hd_list = [], [], [], []
        lines = header_as_text.split('\n')
        print("NUMBER OF LINES::::::::::::::::: %s" % str(len(lines)))
        for line in lines:
            if line.startswith('@SQ'):
                sq_list.append(line)
            elif line.startswith('@HD'):
                hd_list.append(line)
            elif line.startswith('@PG'):
                pg_list.append(line)
            elif line.startswith('@RG'):
                rg_list.append(line)
        print("FROM PARSE ------------------------- RG tag: %s" % str(len(rg_list)))
        #print("FROM PARSE -------------------------  tag: %s" % rg_list)
        return SAMFileHeader(rg_tag=rg_list, pg_tag=pg_list, hd_tag=hd_list, sq_tag=sq_list)


class SAMFileRGTagParser:

    @classmethod
    def _from_read_grp_to_dict(cls, read_grp):
        result = {}
        rg_tags = read_grp.split('\t')
        for tag in rg_tags[1:]:
            tokens = tag.split(':', 1)
            if len(tokens) < 2:
                print("What threw an exception: %s" % tokens)
                raise ValueError("The read grp is not formatted correctly.")
            result[tokens[0]] = tokens[1]
        return result


    @classmethod
    def parse(cls, read_grps):
        seq_center_list, seq_dates, lanelets, platforms, libraries, samples, platform_units = [], [], [], [], [], [], []
        print("From SAMFILE, the tags: %s" % read_grps)
        print("From SAMFILE, the tags: %s" % str(type(read_grps)))
        for read_grp in read_grps:
            read_grp_dict = cls._from_read_grp_to_dict(read_grp)
            if 'CN' in read_grp_dict:
                seq_center_list.append(read_grp_dict['CN'])
            if 'DT' in read_grp_dict:
                seq_dates.append(read_grp_dict['DT'])
            if 'SM' in read_grp_dict:
                samples.append(read_grp_dict['SM'])
            if 'LB' in read_grp_dict:
                libraries.append(read_grp_dict['LB'])
            if 'PU' in read_grp_dict:
                platform_units.append(read_grp_dict['PU'])
            if 'PL' in read_grp_dict:
                platforms.append(read_grp_dict['PL'])

        return SAMFileHeader.RGTag(
            seq_centers=[_f for _f in list(set(seq_center_list)) if _f],
            seq_dates=[_f for _f in list(set(seq_dates)) if _f],
            lanelets=[_f for _f in list(set(lanelets)) if _f],
            platforms=[_f for _f in list(set(platforms)) if _f],
            libraries=[_f for _f in list(set(libraries)) if _f],
            samples=[_f for _f in list(set(samples)) if _f],
            platform_units=[_f for _f in list(set(platform_units)) if _f]
        )


class SangerSeqSAMFileRGTagParser:

#    class RGTagParser:
    LANELET_NAME_REGEX = '[0-9]{4}_[0-9]{1}#[0-9]{1,2}'
    LANE_NAME_REGEX = '[0-9]{4}_[0-9]{1}'

    @classmethod
    def parse(cls, tags: typing.Sequence):
        """ This method parses all the RGs (ReadGroup) in the list received as parameter
        and returns a BAMHeaderRG containing the information found there.
        Parameters
        ----------
        rgs_list: list
{'fraction_non_alphanumeric': 0.10886451907699338, 'fraction_numerical': 0.0065113091158327625, 'mean_word_length': 2.2570684523809526, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2127264', 'n_tokens_mistral': 2658, 'n_tokens_neox': 2590, 'n_words': 835}