{-# LANGUAGE DeriveDataTypeable          #-}
{-# LANGUAGE DeriveGeneric               #-}
{-# LANGUAGE FlexibleContexts            #-}
{-# LANGUAGE FlexibleInstances           #-}
{-# LANGUAGE MultiParamTypeClasses       #-}
{-# LANGUAGE OverloadedStrings           #-}
{-# LANGUAGE TypeFamilies                #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}

-- |
-- Module      :  Data.SAM.Version1_6.Alignment.Base
-- Copyright   :  (c) Matthew Mosior 2023
-- License     :  BSD-style
-- Maintainer  :  mattm.github@gmail.com
-- Portability :  portable
--
-- = Description
--
-- This library enables the decoding/encoding of SAM, BAM and CRAM file formats.

module Data.SAM.Version1_6.Alignment.Base ( -- * SAM version 1.6 alignment mandatory and optional data types
                                            SAM_V1_6_Alignment(..)
                                          ) where

import Data.SAM.Version1_6.Alignment.AOPT
import Data.SAM.Version1_6.Alignment.IOPT
import Data.SAM.Version1_6.Alignment.FOPT
import Data.SAM.Version1_6.Alignment.ZOPT
import Data.SAM.Version1_6.Alignment.HOPT
import Data.SAM.Version1_6.Alignment.BOPT

import Data.ByteString
import Data.Data
import Generics.Deriving.Base

-- | Custom SAM (version 1.6) @"SAM_V1_6_Alignment"@ data type.
--
-- See section 1.4 and 1.5 of the [SAM v1.6](http://samtools.github.io/hts-specs/SAMv1.pdf) specification documentation.
data SAM_V1_6_Alignment = SAM_V1_6_Alignment { SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_qname :: ByteString                    -- ^ Query template NAME.
                                                                                                         -- reads/segments having identical QNAME are regarded to come from
                                                                                                         -- the same template. A QNAME ‘*’ indicates the information
                                                                                                         -- is unavailable. In a SAM file, a read may
                                                                                                         -- occupy multiple alignment lines, when its alignment is chimeric
                                                                                                         -- or when multiple mappings are given.
                                             , SAM_V1_6_Alignment -> Int
sam_v1_6_alignment_flag  :: Int                           -- ^ Combination of bitwise FLAGs.
                                             , SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_rname :: ByteString                    -- ^ Reference sequence NAME of the alignment.
                                                                                                         -- If @SQ header lines are present, RNAME (if not
                                                                                                         -- ‘*’) must be present in one of the SQ-SN tag.
                                                                                                         -- An unmapped segment without coordinate has a ‘*’ at
                                                                                                         -- this field. However, an unmapped segment may also have
                                                                                                         -- an ordinary coordinate such that it can be
                                                                                                         -- placed at a desired position after sorting.
                                                                                                         -- If RNAME is ‘*’, no assumptions can be made about POS
                                                                                                         -- and CIGAR.
                                             , SAM_V1_6_Alignment -> Integer
sam_v1_6_alignment_pos   :: Integer                       -- ^ 1-based leftmost mapping POSition of the first CIGAR
                                                                                                         -- operation that “consumes” a reference
                                                                                                         -- base. The first base in a reference sequence has coordinate 1.
                                                                                                         -- POS is set as 0 for an unmapped read without coordinate.
                                                                                                         -- If POS is 0, no assumptions can be made about RNAME and CIGAR.
                                             , SAM_V1_6_Alignment -> Int
sam_v1_6_alignment_mapq  :: Int                           -- ^ MAPping Quality. It equals −10 log10 Pr{mapping position is wrong},
                                                                                                         -- rounded to the nearest integer. A value 255 indicates that the
                                                                                                         -- mapping quality is not available.
                                             , SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_cigar :: ByteString                    -- ^ CIGAR string (set ‘*’ if unavailable).
                                             , SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_rnext :: ByteString                    -- ^ Reference sequence name of the primary alignment of the
                                                                                                         -- NEXT read in the template. For the last read, the next read
                                                                                                         -- is the first read in the template. If @SQ header lines are present,
                                                                                                         -- RNEXT (if not ‘*’ or ‘=’) must be present in one of the SQ-SN tag.
                                                                                                         -- This field is set as ‘*’ when the information is unavailable,
                                                                                                         -- and set as ‘=’ if RNEXT is identical RNAME. If not ‘=’ and the next
                                                                                                         -- read in the template has one primary mapping (see also bit 0x100 in FLAG),
                                                                                                         -- this field is identical to RNAME at the primary line of the next read.
                                                                                                         -- If RNEXT is ‘*’, no assumptions can be made on PNEXT and bit 0x20.
                                             , SAM_V1_6_Alignment -> Integer
sam_v1_6_alignment_pnext :: Integer                       -- ^ 1-based Position of the primary alignment of the NEXT read in
                                                                                                         -- the template. Set as 0 when the information is unavailable.
                                                                                                         -- This field equals POS at the primary line of the next read.
                                                                                                         -- If PNEXT is 0, no assumptions can be made on RNEXT and bit 0x20.
                                             , SAM_V1_6_Alignment -> Integer
sam_v1_6_alignment_tlen  :: Integer                       -- ^ signed observed Template LENgth. For primary reads where the primary
                                                                                                         -- alignments of all reads in the template are mapped to the same reference
                                                                                                         -- sequence, the absolute value of TLEN equals the distance between the
                                                                                                         -- mapped end of the template and the mapped start of the template,
                                                                                                         -- inclusively (i.e., end − start + 1).
                                                                                                         -- Note that mapped base is defined to be one that aligns to the
                                                                                                         -- reference as described by CIGAR, hence excludes soft-clipped bases.
                                                                                                         -- The TLEN field is positive for the leftmost segment of the template,
                                                                                                         -- negative for the rightmost, and the sign for any middle segment is undefined.
                                                                                                         -- If segments cover the same coordinates then the choice of which is leftmost
                                                                                                         -- and rightmost is arbitrary, but the two ends must still have differing signs.
                                                                                                         -- It is set as 0 for a single-segment template or when the information
                                                                                                         -- is unavailable (e.g., when the first or last segment of a multi-segment
                                                                                                         -- template is unmapped or when the two are mapped to
                                                                                                         -- different reference sequences).
                                             , SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_seq   :: ByteString                    -- ^ segment SEQuence. This field can be a ‘*’ when the sequence
                                                                                                         -- is not stored. If not a ‘*’, the length of the sequence must
                                                                                                         -- equal the sum of lengths of M/I/S/=/X operations in CIGAR.
                                                                                                         -- An ‘=’ denotes the base is identical to the reference base.
                                                                                                         -- No assumptions can be made on the letter cases.
                                             , SAM_V1_6_Alignment -> ByteString
sam_v1_6_alignment_qual  :: ByteString                    -- ^ ASCII of base QUALity plus 33 (same as the quality string
                                                                                                         -- in the Sanger FASTQ format). A base quality is the phred-scaled
                                                                                                         -- base error probability which equals −10 log10 Pr{base is wrong}.
                                                                                                         -- This field can be a ‘*’ when quality is not stored.
                                                                                                         -- If not a ‘*’, SEQ must not be a ‘*’ and the length of the quality
                                                                                                         -- string ought to equal the length of SEQ.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_AOPT
sam_v1_6_alignment_aopt  :: Maybe SAM_V1_6_Alignment_AOPT -- ^ A - [!-~] - Printable characters.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_IOPT
sam_v1_6_alignment_iopt  :: Maybe SAM_V1_6_Alignment_IOPT -- ^ i - [-+]?[0-9]+ - Signed integer.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_FOPT
sam_v1_6_alignment_fopt  :: Maybe SAM_V1_6_Alignment_FOPT -- ^ f - [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? - Single-precision floating number.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_ZOPT
sam_v1_6_alignment_zopt  :: Maybe SAM_V1_6_Alignment_ZOPT -- ^ Z - [ !-~]* - Printable string, including space.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_HOPT
sam_v1_6_alignment_hopt  :: Maybe SAM_V1_6_Alignment_HOPT -- ^ H - ([0-9A-F][0-9A-F])* - Byte array in the Hex format.
                                             , SAM_V1_6_Alignment -> Maybe SAM_V1_6_Alignment_BOPT
sam_v1_6_alignment_bopt  :: Maybe SAM_V1_6_Alignment_BOPT -- ^ B - [cCsSiIf]​(,[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)* - Integer or numeric array.
                                             }
  deriving ((forall x. SAM_V1_6_Alignment -> Rep SAM_V1_6_Alignment x)
-> (forall x. Rep SAM_V1_6_Alignment x -> SAM_V1_6_Alignment)
-> Generic SAM_V1_6_Alignment
forall x. Rep SAM_V1_6_Alignment x -> SAM_V1_6_Alignment
forall x. SAM_V1_6_Alignment -> Rep SAM_V1_6_Alignment x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SAM_V1_6_Alignment -> Rep SAM_V1_6_Alignment x
from :: forall x. SAM_V1_6_Alignment -> Rep SAM_V1_6_Alignment x
$cto :: forall x. Rep SAM_V1_6_Alignment x -> SAM_V1_6_Alignment
to :: forall x. Rep SAM_V1_6_Alignment x -> SAM_V1_6_Alignment
Generic,Typeable)

instance Eq SAM_V1_6_Alignment where
  SAM_V1_6_Alignment ByteString
sam_v1_6_alignment_qname1
                     Int
sam_v1_6_alignment_flag1
                     ByteString
sam_v1_6_alignment_rname1
                     Integer
sam_v1_6_alignment_pos1
                     Int
sam_v1_6_alignment_mapq1
                     ByteString
sam_v1_6_alignment_cigar1
                     ByteString
sam_v1_6_alignment_rnext1
                     Integer
sam_v1_6_alignment_pnext1
                     Integer
sam_v1_6_alignment_tlen1
                     ByteString
sam_v1_6_alignment_seq1
                     ByteString
sam_v1_6_alignment_qual1
                     Maybe SAM_V1_6_Alignment_AOPT
sam_v1_6_alignment_aopt1
                     Maybe SAM_V1_6_Alignment_IOPT
sam_v1_6_alignment_iopt1
                     Maybe SAM_V1_6_Alignment_FOPT
sam_v1_6_alignment_fopt1
                     Maybe SAM_V1_6_Alignment_ZOPT
sam_v1_6_alignment_zopt1
                     Maybe SAM_V1_6_Alignment_HOPT
sam_v1_6_alignment_hopt1
                     Maybe SAM_V1_6_Alignment_BOPT
sam_v1_6_alignment_bopt1 == :: SAM_V1_6_Alignment -> SAM_V1_6_Alignment -> Bool
== SAM_V1_6_Alignment ByteString
sam_v1_6_alignment_qname2
                                                                    Int
sam_v1_6_alignment_flag2
                                                                    ByteString
sam_v1_6_alignment_rname2
                                                                    Integer
sam_v1_6_alignment_pos2
                                                                    Int
sam_v1_6_alignment_mapq2
                                                                    ByteString
sam_v1_6_alignment_cigar2
                                                                    ByteString
sam_v1_6_alignment_rnext2
                                                                    Integer
sam_v1_6_alignment_pnext2
                                                                    Integer
sam_v1_6_alignment_tlen2
                                                                    ByteString
sam_v1_6_alignment_seq2
                                                                    ByteString
sam_v1_6_alignment_qual2
                                                                    Maybe SAM_V1_6_Alignment_AOPT
sam_v1_6_alignment_aopt2
                                                                    Maybe SAM_V1_6_Alignment_IOPT
sam_v1_6_alignment_iopt2
                                                                    Maybe SAM_V1_6_Alignment_FOPT
sam_v1_6_alignment_fopt2
                                                                    Maybe SAM_V1_6_Alignment_ZOPT
sam_v1_6_alignment_zopt2
                                                                    Maybe SAM_V1_6_Alignment_HOPT
sam_v1_6_alignment_hopt2
                                                                    Maybe SAM_V1_6_Alignment_BOPT
sam_v1_6_alignment_bopt2 = ByteString
sam_v1_6_alignment_qname1 ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_qname2 Bool -> Bool -> Bool
&&  
                                                                                               Int
sam_v1_6_alignment_flag1  Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
sam_v1_6_alignment_flag2  Bool -> Bool -> Bool
&&
                                                                                               ByteString
sam_v1_6_alignment_rname1 ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_rname2 Bool -> Bool -> Bool
&&
                                                                                               Integer
sam_v1_6_alignment_pos1   Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
sam_v1_6_alignment_pos2   Bool -> Bool -> Bool
&&
                                                                                               Int
sam_v1_6_alignment_mapq1  Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
sam_v1_6_alignment_mapq2  Bool -> Bool -> Bool
&&
                                                                                               ByteString
sam_v1_6_alignment_cigar1 ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_cigar2 Bool -> Bool -> Bool
&&
                                                                                               ByteString
sam_v1_6_alignment_rnext1 ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_rnext2 Bool -> Bool -> Bool
&&
                                                                                               Integer
sam_v1_6_alignment_pnext1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
sam_v1_6_alignment_pnext2 Bool -> Bool -> Bool
&&
                                                                                               Integer
sam_v1_6_alignment_tlen1  Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
sam_v1_6_alignment_tlen2  Bool -> Bool -> Bool
&&
                                                                                               ByteString
sam_v1_6_alignment_seq1   ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_seq2   Bool -> Bool -> Bool
&&
                                                                                               ByteString
sam_v1_6_alignment_qual1  ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
sam_v1_6_alignment_qual2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_AOPT
sam_v1_6_alignment_aopt1  Maybe SAM_V1_6_Alignment_AOPT
-> Maybe SAM_V1_6_Alignment_AOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_AOPT
sam_v1_6_alignment_aopt2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_IOPT
sam_v1_6_alignment_iopt1  Maybe SAM_V1_6_Alignment_IOPT
-> Maybe SAM_V1_6_Alignment_IOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_IOPT
sam_v1_6_alignment_iopt2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_FOPT
sam_v1_6_alignment_fopt1  Maybe SAM_V1_6_Alignment_FOPT
-> Maybe SAM_V1_6_Alignment_FOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_FOPT
sam_v1_6_alignment_fopt2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_ZOPT
sam_v1_6_alignment_zopt1  Maybe SAM_V1_6_Alignment_ZOPT
-> Maybe SAM_V1_6_Alignment_ZOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_ZOPT
sam_v1_6_alignment_zopt2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_HOPT
sam_v1_6_alignment_hopt1  Maybe SAM_V1_6_Alignment_HOPT
-> Maybe SAM_V1_6_Alignment_HOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_HOPT
sam_v1_6_alignment_hopt2  Bool -> Bool -> Bool
&&
                                                                                               Maybe SAM_V1_6_Alignment_BOPT
sam_v1_6_alignment_bopt1  Maybe SAM_V1_6_Alignment_BOPT
-> Maybe SAM_V1_6_Alignment_BOPT -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe SAM_V1_6_Alignment_BOPT
sam_v1_6_alignment_bopt2

instance Show SAM_V1_6_Alignment where
  show :: SAM_V1_6_Alignment -> String
show (SAM_V1_6_Alignment ByteString
qname Int
flag ByteString
rname Integer
pos Int
mapq ByteString
cigar ByteString
rnext Integer
pnext Integer
tlen ByteString
seq ByteString
qual Maybe SAM_V1_6_Alignment_AOPT
aopt Maybe SAM_V1_6_Alignment_IOPT
iopt Maybe SAM_V1_6_Alignment_FOPT
fopt Maybe SAM_V1_6_Alignment_ZOPT
zopt Maybe SAM_V1_6_Alignment_HOPT
hopt Maybe SAM_V1_6_Alignment_BOPT
bopt) =
    String
"SAM_V1_6_Alignment { "          String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
"sam_v1_6_alignment_qname = "    String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
qname)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_flag = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Int -> String
forall a. Show a => a -> String
show Int
flag)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_rname = " String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
rname)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_pos = "   String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Integer -> String
forall a. Show a => a -> String
show Integer
pos)                       String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_mapq = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Int -> String
forall a. Show a => a -> String
show Int
mapq)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_cigar = " String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
cigar)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_rnext = " String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
rnext)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_pnext = " String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Integer -> String
forall a. Show a => a -> String
show Integer
pnext)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_tlen = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Integer -> String
forall a. Show a => a -> String
show Integer
tlen)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_seq = "   String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
seq)                       String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_qual = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (ByteString -> String
forall a. Show a => a -> String
show ByteString
qual)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_aopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    ( Maybe SAM_V1_6_Alignment_AOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_AOPT
aopt)                     String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_iopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Maybe SAM_V1_6_Alignment_IOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_IOPT
iopt)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_fopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Maybe SAM_V1_6_Alignment_FOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_FOPT
fopt)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_zopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Maybe SAM_V1_6_Alignment_ZOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_ZOPT
zopt)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_hopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Maybe SAM_V1_6_Alignment_HOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_HOPT
hopt)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" , sam_v1_6_alignment_bopt = "  String -> ShowS
forall a. [a] -> [a] -> [a]
++
    (Maybe SAM_V1_6_Alignment_BOPT -> String
forall a. Show a => a -> String
show Maybe SAM_V1_6_Alignment_BOPT
bopt)                      String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" }"