{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE InstanceSigs           #-}
{-# LANGUAGE MultiParamTypeClasses  #-}

module HaskellWorks.Data.Json.Type
  ( JsonType(..)
  , JsonTypeAt(..)
  ) where

import qualified Data.ByteString                                            as BS
import           Data.Char
import           Data.Word8
import           HaskellWorks.Data.Bits.BitWise
import           HaskellWorks.Data.Json.Succinct
import           HaskellWorks.Data.Positioning
import qualified HaskellWorks.Data.Succinct.BalancedParens                  as BP
import           HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank0
import           HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Rank1
import           HaskellWorks.Data.Succinct.RankSelect.Binary.Basic.Select1
import           HaskellWorks.Data.Vector.VectorLike

wIsJsonNumberDigit :: Word8 -> Bool
wIsJsonNumberDigit :: Word8 -> Bool
wIsJsonNumberDigit Word8
w = (Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
_0 Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
_9) Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_hyphen

data JsonType
  = JsonTypeArray
  | JsonTypeBool
  | JsonTypeNull
  | JsonTypeNumber
  | JsonTypeObject
  | JsonTypeString
  deriving (JsonType -> JsonType -> Bool
(JsonType -> JsonType -> Bool)
-> (JsonType -> JsonType -> Bool) -> Eq JsonType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JsonType -> JsonType -> Bool
$c/= :: JsonType -> JsonType -> Bool
== :: JsonType -> JsonType -> Bool
$c== :: JsonType -> JsonType -> Bool
Eq, Int -> JsonType -> ShowS
[JsonType] -> ShowS
JsonType -> String
(Int -> JsonType -> ShowS)
-> (JsonType -> String) -> ([JsonType] -> ShowS) -> Show JsonType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [JsonType] -> ShowS
$cshowList :: [JsonType] -> ShowS
show :: JsonType -> String
$cshow :: JsonType -> String
showsPrec :: Int -> JsonType -> ShowS
$cshowsPrec :: Int -> JsonType -> ShowS
Show)

class JsonTypeAt a where
  jsonTypeAtPosition :: Position -> a -> Maybe JsonType
  jsonTypeAt :: a -> Maybe JsonType

instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (JsonCursor String v w) where
  jsonTypeAtPosition :: Position -> JsonCursor String v w -> Maybe JsonType
jsonTypeAtPosition Position
p JsonCursor String v w
k = case Count -> ShowS
forall v. Seq v => Count -> v -> v
vDrop (Position -> Count
toCount Position
p) (JsonCursor String v w -> String
forall t v w. JsonCursor t v w -> t
cursorText JsonCursor String v w
k) of
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_bracketleft      -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeArray
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_f                -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeBool
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_t                -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeBool
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_n                -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeNull
    Char
c:String
_ | Word8 -> Bool
wIsJsonNumberDigit (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c)) -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeNumber
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_braceleft        -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeObject
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl         -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeString
    String
_                                               -> Maybe JsonType
forall a. Maybe a
Nothing

  jsonTypeAt :: JsonCursor String v w -> Maybe JsonType
jsonTypeAt JsonCursor String v w
k = Position -> JsonCursor String v w -> Maybe JsonType
forall a. JsonTypeAt a => Position -> a -> Maybe JsonType
jsonTypeAtPosition Position
p JsonCursor String v w
k
    where p :: Position
p   = Count -> Position
lastPositionOf (v -> Count -> Count
forall v. Select1 v => v -> Count -> Count
select1 v
ik (w -> Count -> Count
forall v. Rank1 v => v -> Count -> Count
rank1 w
bpk (JsonCursor String v w -> Count
forall t v w. JsonCursor t v w -> Count
cursorRank JsonCursor String v w
k)))
          ik :: v
ik  = JsonCursor String v w -> v
forall t v w. JsonCursor t v w -> v
interests JsonCursor String v w
k
          bpk :: w
bpk = JsonCursor String v w -> w
forall t v w. JsonCursor t v w -> w
balancedParens JsonCursor String v w
k

instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (JsonCursor BS.ByteString v w) where
  jsonTypeAtPosition :: Position -> JsonCursor ByteString v w -> Maybe JsonType
jsonTypeAtPosition Position
p JsonCursor ByteString v w
k = case ByteString -> Maybe (Word8, ByteString)
BS.uncons (Count -> ByteString -> ByteString
forall v. Seq v => Count -> v -> v
vDrop (Position -> Count
toCount Position
p) (JsonCursor ByteString v w -> ByteString
forall t v w. JsonCursor t v w -> t
cursorText JsonCursor ByteString v w
k)) of
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_bracketleft     -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeArray
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_f               -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeBool
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_t               -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeBool
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_n               -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeNull
    Just (Word8
c, ByteString
_) | Word8 -> Bool
wIsJsonNumberDigit Word8
c  -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeNumber
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_braceleft       -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeObject
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl        -> JsonType -> Maybe JsonType
forall a. a -> Maybe a
Just JsonType
JsonTypeString
    Maybe (Word8, ByteString)
_                                   -> Maybe JsonType
forall a. Maybe a
Nothing

  jsonTypeAt :: JsonCursor ByteString v w -> Maybe JsonType
jsonTypeAt JsonCursor ByteString v w
k = Position -> JsonCursor ByteString v w -> Maybe JsonType
forall a. JsonTypeAt a => Position -> a -> Maybe JsonType
jsonTypeAtPosition Position
p JsonCursor ByteString v w
k
    where p :: Position
p   = Count -> Position
lastPositionOf (v -> Count -> Count
forall v. Select1 v => v -> Count -> Count
select1 v
ik (w -> Count -> Count
forall v. Rank1 v => v -> Count -> Count
rank1 w
bpk (JsonCursor ByteString v w -> Count
forall t v w. JsonCursor t v w -> Count
cursorRank JsonCursor ByteString v w
k)))
          ik :: v
ik  = JsonCursor ByteString v w -> v
forall t v w. JsonCursor t v w -> v
interests JsonCursor ByteString v w
k
          bpk :: w
bpk = JsonCursor ByteString v w -> w
forall t v w. JsonCursor t v w -> w
balancedParens JsonCursor ByteString v w
k