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

-- |
-- Module      :  Data.SAM.Version1_6.Alignment.Base
-- Copyright   :  (c) Matthew Mosior 2024
-- 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.OptionalFields.Base

import Data.ByteString
import Data.Data
import Data.Sequence
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 (Seq SAM_V1_6_Alignment_OptionalFields)
sam_v1_6_alignment_optionalfields :: Maybe (Seq SAM_V1_6_Alignment_OptionalFields) -- ^ Optional fields.
  } 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 (Seq SAM_V1_6_Alignment_OptionalFields)
sam_v1_6_alignment_optfields1 == :: 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 (Seq SAM_V1_6_Alignment_OptionalFields)
sam_v1_6_alignment_optfields2 =
      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 (Seq SAM_V1_6_Alignment_OptionalFields)
sam_v1_6_alignment_optfields1 Maybe (Seq SAM_V1_6_Alignment_OptionalFields)
-> Maybe (Seq SAM_V1_6_Alignment_OptionalFields) -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe (Seq SAM_V1_6_Alignment_OptionalFields)
sam_v1_6_alignment_optfields2

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 (Seq SAM_V1_6_Alignment_OptionalFields)
optfields
       ) =
    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_optionalfields = " String -> ShowS
forall a. [a] -> [a] -> [a]
++
    ( Maybe (Seq SAM_V1_6_Alignment_OptionalFields) -> String
forall a. Show a => a -> String
show Maybe (Seq SAM_V1_6_Alignment_OptionalFields)
optfields)                         String -> ShowS
forall a. [a] -> [a] -> [a]
++
    String
" }"