{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies          #-}

-- |
-- Module      :  Data.BAM.Version1_6.Read.Parser.BAM.BAMHeader
-- 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.BAM.Version1_6.Read.Parser.BAM.BAMHeader ( -- * BAM_V1_6_BAM_BAMHeader parser
                                                       parse_BAM_V1_6_BAM_BAMHeader
                                                     ) where

import Data.BAM.Version1_6.Internal
import Data.BAM.Version1_6.BAM.BAMHeader
import Data.BAM.Version1_6.Read.Error
import Data.BAM.Version1_6.Read.Parser.BAM.ReferenceInformation.Base

import Data.Attoparsec.ByteString.Lazy as DABL
import Data.ByteString                 as DB
import Data.Sequence                   as DSeq

-- | Define the @"BAM_V1_6_BAM_BAMHeader"@ parser.
parse_BAM_V1_6_BAM_BAMHeader :: Parser BAM_V1_6_BAM_BAMHeader
parse_BAM_V1_6_BAM_BAMHeader :: Parser BAM_V1_6_BAM_BAMHeader
parse_BAM_V1_6_BAM_BAMHeader = do
  ByteString
magic                 <- do
    ByteString
magicp <-
      Int -> Parser ByteString ByteString
DABL.take Int
4
    case (ByteString
magicp ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
bammagicstring) of
      Bool
False ->
        String -> Parser ByteString ByteString
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser ByteString ByteString)
-> String -> Parser ByteString ByteString
forall a b. (a -> b) -> a -> b
$
          BAM_V1_6_Read_Error -> String
forall a. Show a => a -> String
show BAM_V1_6_Read_Error
BAM_V1_6_Read_Error_BAMHeader_BAM_Magic_String_Invalid_Value
      Bool
True ->
        ByteString -> Parser ByteString ByteString
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
magicp
  ByteString
l_text                <-
    Int -> Parser ByteString ByteString
DABL.take Int
4
  ByteString
text                  <-
    Int -> Parser ByteString ByteString
DABL.take
      ( Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral       (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$
          [Word8] -> Word32
word8sToWord32LE ([Word8] -> Word32) -> [Word8] -> Word32
forall a b. (a -> b) -> a -> b
$
            ByteString -> [Word8]
DB.unpack ByteString
l_text -- :: Int
      )
  ByteString
n_ref                 <-
    Int -> Parser ByteString ByteString
DABL.take Int
4
  [BAM_V1_6_BAM_Reference_Information]
reference_information <-
    Int
-> Parser ByteString BAM_V1_6_BAM_Reference_Information
-> Parser ByteString [BAM_V1_6_BAM_Reference_Information]
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
DABL.count ( Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral       (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$
                   [Word8] -> Word32
word8sToWord32LE ([Word8] -> Word32) -> [Word8] -> Word32
forall a b. (a -> b) -> a -> b
$
                     ByteString -> [Word8]
DB.unpack ByteString
n_ref :: Int
               )
               Parser ByteString BAM_V1_6_BAM_Reference_Information
parse_BAM_V1_6_BAM_Reference_Information
  BAM_V1_6_BAM_BAMHeader -> Parser BAM_V1_6_BAM_BAMHeader
forall a. a -> Parser ByteString a
forall (m :: * -> *) a. Monad m => a -> m a
return BAM_V1_6_BAM_BAMHeader
           { bam_v1_6_bam_bamheader_magic :: ByteString
bam_v1_6_bam_bamheader_magic                 = ByteString
magic
           , bam_v1_6_bam_bamheader_l_text :: Word32
bam_v1_6_bam_bamheader_l_text                = [Word8] -> Word32
word8sToWord32LE ([Word8] -> Word32) -> [Word8] -> Word32
forall a b. (a -> b) -> a -> b
$
                                                              ByteString -> [Word8]
DB.unpack ByteString
l_text
           , bam_v1_6_bam_bamheader_text :: ByteString
bam_v1_6_bam_bamheader_text                  = ByteString
text
           , bam_v1_6_bam_bamheader_n_ref :: Word32
bam_v1_6_bam_bamheader_n_ref                 = [Word8] -> Word32
word8sToWord32LE ([Word8] -> Word32) -> [Word8] -> Word32
forall a b. (a -> b) -> a -> b
$
                                                              ByteString -> [Word8]
DB.unpack ByteString
n_ref
           , bam_v1_6_bam_bamheader_reference_information :: Seq BAM_V1_6_BAM_Reference_Information
bam_v1_6_bam_bamheader_reference_information = [BAM_V1_6_BAM_Reference_Information]
-> Seq BAM_V1_6_BAM_Reference_Information
forall a. [a] -> Seq a
DSeq.fromList [BAM_V1_6_BAM_Reference_Information]
reference_information
           }
  where
    bammagicstring :: ByteString
bammagicstring = [Word8] -> ByteString
DB.pack [ Word8
0x42
                             , Word8
0x41
                             , Word8
0x4D
                             , Word8
0x01
                             ]