{-| Utilities for manipulating nucleotide sequences and locations on
nucleotide sequences that occur on a forward or a reverse-complement
strand.

-}

module Bio.Location.Strand ( Strand(..)
                           , Stranded(..), stranded
                           )
    where 

import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Ix (Ix)

import Bio.Sequence.SeqData

-- | Sequence strand
data Strand = Fwd | RevCompl deriving (Eq, Ord, Show, Read, Bounded, Enum, Ix)

-- | A nucleotide sequence or location on a nucleotide sequence that
--   lies on a specific strand and has an orientation.
class Stranded s where
    revCompl :: s -> s

-- | Convert the orientation of a 'Stranded' thing based on a
--   specified 'Strand'
stranded :: (Stranded s) => Strand -> s -> s
stranded Fwd      = id
stranded RevCompl = revCompl

instance Stranded Strand where
    revCompl Fwd      = RevCompl
    revCompl RevCompl = Fwd

instance Stranded Char where
    revCompl = compl

-- Avoid using -XTypeSynonymInstances
instance Stranded LBS.ByteString where
    revCompl = LBS.reverse . LBS.map compl