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

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

import Data.Char
import Data.String
import Data.Word8
import GHC.Generics
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Drop
import HaskellWorks.Data.Json.Standard.Cursor.Generic
import HaskellWorks.Data.Json.Standard.Cursor.Internal.Word8
import HaskellWorks.Data.Positioning
import HaskellWorks.Data.RankSelect.Base.Rank0
import HaskellWorks.Data.RankSelect.Base.Rank1
import HaskellWorks.Data.RankSelect.Base.Select1
import Prelude                                               hiding (drop)

import qualified Data.ByteString                  as BS
import qualified HaskellWorks.Data.BalancedParens as BP

{- HLINT ignore "Reduce duplication"  -}

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, (forall x. JsonType -> Rep JsonType x)
-> (forall x. Rep JsonType x -> JsonType) -> Generic JsonType
forall x. Rep JsonType x -> JsonType
forall x. JsonType -> Rep JsonType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep JsonType x -> JsonType
$cfrom :: forall x. JsonType -> Rep JsonType x
Generic)

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 (GenericCursor String v w) where
  jsonTypeAtPosition :: Position -> GenericCursor String v w -> Maybe JsonType
jsonTypeAtPosition Position
p GenericCursor String v w
k = case Count -> ShowS
forall v. Drop v => Count -> v -> v
drop (Position -> Count
forall a. ToCount a => a -> Count
toCount Position
p) (GenericCursor String v w -> String
forall t v w. GenericCursor t v w -> t
cursorText GenericCursor 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 :: GenericCursor String v w -> Maybe JsonType
jsonTypeAt GenericCursor String v w
k = Position -> GenericCursor String v w -> Maybe JsonType
forall a. JsonTypeAt a => Position -> a -> Maybe JsonType
jsonTypeAtPosition Position
p GenericCursor 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 (GenericCursor String v w -> Count
forall t v w. GenericCursor t v w -> Count
cursorRank GenericCursor String v w
k)))
          ik :: v
ik  = GenericCursor String v w -> v
forall t v w. GenericCursor t v w -> v
interests GenericCursor String v w
k
          bpk :: w
bpk = GenericCursor String v w -> w
forall t v w. GenericCursor t v w -> w
balancedParens GenericCursor String v w
k

instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => JsonTypeAt (GenericCursor BS.ByteString v w) where
  jsonTypeAtPosition :: Position -> GenericCursor ByteString v w -> Maybe JsonType
jsonTypeAtPosition Position
p GenericCursor ByteString v w
k = case ByteString -> Maybe (Word8, ByteString)
BS.uncons (Count -> ByteString -> ByteString
forall v. Drop v => Count -> v -> v
drop (Position -> Count
forall a. ToCount a => a -> Count
toCount Position
p) (GenericCursor ByteString v w -> ByteString
forall t v w. GenericCursor t v w -> t
cursorText GenericCursor 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 :: GenericCursor ByteString v w -> Maybe JsonType
jsonTypeAt GenericCursor ByteString v w
k = Position -> GenericCursor ByteString v w -> Maybe JsonType
forall a. JsonTypeAt a => Position -> a -> Maybe JsonType
jsonTypeAtPosition Position
p GenericCursor 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 (GenericCursor ByteString v w -> Count
forall t v w. GenericCursor t v w -> Count
cursorRank GenericCursor ByteString v w
k)))
          ik :: v
ik  = GenericCursor ByteString v w -> v
forall t v w. GenericCursor t v w -> v
interests GenericCursor ByteString v w
k
          bpk :: w
bpk = GenericCursor ByteString v w -> w
forall t v w. GenericCursor t v w -> w
balancedParens GenericCursor ByteString v w
k