module Biobase.Primary.Nuc.XNA where

import           Data.Aeson
import           Data.Char (toUpper)
import           Data.Ix (Ix(..))
import           Data.Primitive.Types
import           Data.String
import           Data.Tuple (swap)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Unboxed as VU
import           Control.Category ((>>>))

import           Biobase.Types.BioSequence

import           Biobase.Primary.Bounds
import           Biobase.Primary.Letter



-- | Combine both, RNA and DNA.

pattern $bA :: Letter XNA n
$mA :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
A = Letter 0 :: Letter XNA n
pattern $bC :: Letter XNA n
$mC :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
C = Letter 1 :: Letter XNA n
pattern $bG :: Letter XNA n
$mG :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
G = Letter 2 :: Letter XNA n
pattern $bT :: Letter XNA n
$mT :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
T = Letter 3 :: Letter XNA n
pattern $bU :: Letter XNA n
$mU :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
U = Letter 4 :: Letter XNA n
pattern $bN :: Letter XNA n
$mN :: forall r k (n :: k).
Letter XNA n -> (Void# -> r) -> (Void# -> r) -> r
N = Letter 5 :: Letter XNA n

instance Bounded (Letter XNA n) where
    minBound :: Letter XNA n
minBound = Letter XNA n
forall k (n :: k). Letter XNA n
A
    maxBound :: Letter XNA n
maxBound = Letter XNA n
forall k (n :: k). Letter XNA n
N

instance Enum (Letter XNA n) where
    succ :: Letter XNA n -> Letter XNA n
succ Letter XNA n
N          = [Char] -> Letter XNA n
forall a. HasCallStack => [Char] -> a
error [Char]
"succ/N:XNA"
    succ (Letter Int
x) = Int -> Letter XNA n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter (Int -> Letter XNA n) -> Int -> Letter XNA n
forall a b. (a -> b) -> a -> b
$ Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
    pred :: Letter XNA n -> Letter XNA n
pred Letter XNA n
A          = [Char] -> Letter XNA n
forall a. HasCallStack => [Char] -> a
error [Char]
"pred/A:XNA"
    pred (Letter Int
x) = Int -> Letter XNA n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter (Int -> Letter XNA n) -> Int -> Letter XNA n
forall a b. (a -> b) -> a -> b
$ Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1
    toEnum :: Int -> Letter XNA n
toEnum Int
k | Int
kInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
kInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
5 = Int -> Letter XNA n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter Int
k
    toEnum Int
k                = [Char] -> Letter XNA n
forall a. HasCallStack => [Char] -> a
error ([Char] -> Letter XNA n) -> [Char] -> Letter XNA n
forall a b. (a -> b) -> a -> b
$ [Char]
"toEnum/Letter XNA " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
k
    fromEnum :: Letter XNA n -> Int
fromEnum (Letter Int
k) = Int
k

instance LetterChar XNA n where
  letterChar :: Letter XNA n -> Char
letterChar = Letter XNA n -> Char
forall k (n :: k). Letter XNA n -> Char
xnaChar
  charLetter :: Char -> Letter XNA n
charLetter = Char -> Letter XNA n
forall k (n :: k). Char -> Letter XNA n
charXNA

--instance (LetterChar XNA) => ToJSON (Primary XNA) where
--  toJSON = toJSON . VU.toList . VU.map letterChar
--
--instance (MkPrimary (VU.Vector Char) XNA) => FromJSON (Primary XNA) where
--  parseJSON = fmap (primary :: String -> Primary XNA) . parseJSON

charXNA :: Char -> Letter XNA n
charXNA = Char -> Char
toUpper (Char -> Char) -> (Char -> Letter XNA n) -> Char -> Letter XNA n
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> \case
    Char
'A' -> Letter XNA n
forall k (n :: k). Letter XNA n
A
    Char
'C' -> Letter XNA n
forall k (n :: k). Letter XNA n
C
    Char
'G' -> Letter XNA n
forall k (n :: k). Letter XNA n
G
    Char
'T' -> Letter XNA n
forall k (n :: k). Letter XNA n
T
    Char
'U' -> Letter XNA n
forall k (n :: k). Letter XNA n
U
    Char
_   -> Letter XNA n
forall k (n :: k). Letter XNA n
N
{-# INLINE charXNA #-}

xnaChar :: Letter XNA n -> Char
xnaChar = \case
  Letter XNA n
A -> Char
'A'
  Letter XNA n
C -> Char
'C'
  Letter XNA n
G -> Char
'G'
  Letter XNA n
T -> Char
'T'
  Letter XNA n
U -> Char
'U'
  Letter XNA n
N -> Char
'N'
{-# INLINE xnaChar #-}            

instance Show (Letter XNA n) where
    show :: Letter XNA n -> [Char]
show Letter XNA n
c = [Letter XNA n -> Char
forall k (n :: k). Letter XNA n -> Char
xnaChar Letter XNA n
c]

instance Read (Letter XNA n) where
  readsPrec :: Int -> ReadS (Letter XNA n)
readsPrec Int
p [] = []
  readsPrec Int
p (Char
x:[Char]
xs)
    | Char
xChar -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
' ' = Int -> ReadS (Letter XNA n)
forall a. Read a => Int -> ReadS a
readsPrec Int
p [Char]
xs
    | Bool
otherwise = [(Char -> Letter XNA n
forall k (n :: k). Char -> Letter XNA n
charXNA Char
x, [Char]
xs)]

xnaSeq :: MkPrimary p XNA n => p -> Primary XNA n
xnaSeq :: p -> Primary XNA n
xnaSeq = p -> Primary XNA n
forall k c t (n :: k). MkPrimary c t n => c -> Primary t n
primary

instance MkPrimary (VU.Vector Char) XNA n where
    primary :: Vector Char -> Primary XNA n
primary = (Char -> Letter XNA n) -> Vector Char -> Primary XNA n
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map Char -> Letter XNA n
forall k (n :: k). Char -> Letter XNA n
charXNA

instance IsString [Letter XNA n] where
    fromString :: [Char] -> [Letter XNA n]
fromString = (Char -> Letter XNA n) -> [Char] -> [Letter XNA n]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Letter XNA n
forall k (n :: k). Char -> Letter XNA n
charXNA