-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree.


{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

module Duckling.PhoneNumber.Types where

import Control.DeepSeq
import Data.Aeson
import Data.Hashable
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as Text
import GHC.Generics
import qualified TextShow as TS

import Prelude

import Duckling.Resolve (Resolve(..))

data PhoneNumberData = PhoneNumberData
  { PhoneNumberData -> Maybe Integer
prefix :: Maybe Integer
  , PhoneNumberData -> Text
number :: Text
  , PhoneNumberData -> Maybe Integer
extension :: Maybe Integer
  }
  deriving (PhoneNumberData -> PhoneNumberData -> Bool
(PhoneNumberData -> PhoneNumberData -> Bool)
-> (PhoneNumberData -> PhoneNumberData -> Bool)
-> Eq PhoneNumberData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PhoneNumberData -> PhoneNumberData -> Bool
$c/= :: PhoneNumberData -> PhoneNumberData -> Bool
== :: PhoneNumberData -> PhoneNumberData -> Bool
$c== :: PhoneNumberData -> PhoneNumberData -> Bool
Eq, (forall x. PhoneNumberData -> Rep PhoneNumberData x)
-> (forall x. Rep PhoneNumberData x -> PhoneNumberData)
-> Generic PhoneNumberData
forall x. Rep PhoneNumberData x -> PhoneNumberData
forall x. PhoneNumberData -> Rep PhoneNumberData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PhoneNumberData x -> PhoneNumberData
$cfrom :: forall x. PhoneNumberData -> Rep PhoneNumberData x
Generic, Int -> PhoneNumberData -> Int
PhoneNumberData -> Int
(Int -> PhoneNumberData -> Int)
-> (PhoneNumberData -> Int) -> Hashable PhoneNumberData
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: PhoneNumberData -> Int
$chash :: PhoneNumberData -> Int
hashWithSalt :: Int -> PhoneNumberData -> Int
$chashWithSalt :: Int -> PhoneNumberData -> Int
Hashable, Eq PhoneNumberData
Eq PhoneNumberData
-> (PhoneNumberData -> PhoneNumberData -> Ordering)
-> (PhoneNumberData -> PhoneNumberData -> Bool)
-> (PhoneNumberData -> PhoneNumberData -> Bool)
-> (PhoneNumberData -> PhoneNumberData -> Bool)
-> (PhoneNumberData -> PhoneNumberData -> Bool)
-> (PhoneNumberData -> PhoneNumberData -> PhoneNumberData)
-> (PhoneNumberData -> PhoneNumberData -> PhoneNumberData)
-> Ord PhoneNumberData
PhoneNumberData -> PhoneNumberData -> Bool
PhoneNumberData -> PhoneNumberData -> Ordering
PhoneNumberData -> PhoneNumberData -> PhoneNumberData
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PhoneNumberData -> PhoneNumberData -> PhoneNumberData
$cmin :: PhoneNumberData -> PhoneNumberData -> PhoneNumberData
max :: PhoneNumberData -> PhoneNumberData -> PhoneNumberData
$cmax :: PhoneNumberData -> PhoneNumberData -> PhoneNumberData
>= :: PhoneNumberData -> PhoneNumberData -> Bool
$c>= :: PhoneNumberData -> PhoneNumberData -> Bool
> :: PhoneNumberData -> PhoneNumberData -> Bool
$c> :: PhoneNumberData -> PhoneNumberData -> Bool
<= :: PhoneNumberData -> PhoneNumberData -> Bool
$c<= :: PhoneNumberData -> PhoneNumberData -> Bool
< :: PhoneNumberData -> PhoneNumberData -> Bool
$c< :: PhoneNumberData -> PhoneNumberData -> Bool
compare :: PhoneNumberData -> PhoneNumberData -> Ordering
$ccompare :: PhoneNumberData -> PhoneNumberData -> Ordering
$cp1Ord :: Eq PhoneNumberData
Ord, Int -> PhoneNumberData -> ShowS
[PhoneNumberData] -> ShowS
PhoneNumberData -> String
(Int -> PhoneNumberData -> ShowS)
-> (PhoneNumberData -> String)
-> ([PhoneNumberData] -> ShowS)
-> Show PhoneNumberData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PhoneNumberData] -> ShowS
$cshowList :: [PhoneNumberData] -> ShowS
show :: PhoneNumberData -> String
$cshow :: PhoneNumberData -> String
showsPrec :: Int -> PhoneNumberData -> ShowS
$cshowsPrec :: Int -> PhoneNumberData -> ShowS
Show, PhoneNumberData -> ()
(PhoneNumberData -> ()) -> NFData PhoneNumberData
forall a. (a -> ()) -> NFData a
rnf :: PhoneNumberData -> ()
$crnf :: PhoneNumberData -> ()
NFData)

instance Resolve PhoneNumberData where
  type ResolvedValue PhoneNumberData = PhoneNumberValue
  resolve :: Context
-> Options
-> PhoneNumberData
-> Maybe (ResolvedValue PhoneNumberData, Bool)
resolve Context
_ Options
_ PhoneNumberData {Maybe Integer
prefix :: Maybe Integer
prefix :: PhoneNumberData -> Maybe Integer
prefix, Text
number :: Text
number :: PhoneNumberData -> Text
number, Maybe Integer
extension :: Maybe Integer
extension :: PhoneNumberData -> Maybe Integer
extension} = (PhoneNumberValue, Bool) -> Maybe (PhoneNumberValue, Bool)
forall a. a -> Maybe a
Just
    (PhoneNumberValue :: Text -> PhoneNumberValue
PhoneNumberValue {value :: Text
value = [Text] -> Text
Text.concat [Text
p, Text
number, Text
e]}, Bool
False)
    where
      p :: Text
p = case Maybe Integer
prefix of
        Just Integer
p -> Text
"(+" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Integer -> Text
forall a. TextShow a => a -> Text
TS.showt Integer
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
") "
        Maybe Integer
Nothing -> Text
""
      e :: Text
e = case Maybe Integer
extension of
        Just Integer
e -> Text
" ext " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Integer -> Text
forall a. TextShow a => a -> Text
TS.showt Integer
e
        Maybe Integer
Nothing -> Text
""

data PhoneNumberValue = PhoneNumberValue { PhoneNumberValue -> Text
value :: Text }
  deriving (PhoneNumberValue -> PhoneNumberValue -> Bool
(PhoneNumberValue -> PhoneNumberValue -> Bool)
-> (PhoneNumberValue -> PhoneNumberValue -> Bool)
-> Eq PhoneNumberValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c/= :: PhoneNumberValue -> PhoneNumberValue -> Bool
== :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c== :: PhoneNumberValue -> PhoneNumberValue -> Bool
Eq, Eq PhoneNumberValue
Eq PhoneNumberValue
-> (PhoneNumberValue -> PhoneNumberValue -> Ordering)
-> (PhoneNumberValue -> PhoneNumberValue -> Bool)
-> (PhoneNumberValue -> PhoneNumberValue -> Bool)
-> (PhoneNumberValue -> PhoneNumberValue -> Bool)
-> (PhoneNumberValue -> PhoneNumberValue -> Bool)
-> (PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue)
-> (PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue)
-> Ord PhoneNumberValue
PhoneNumberValue -> PhoneNumberValue -> Bool
PhoneNumberValue -> PhoneNumberValue -> Ordering
PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue
$cmin :: PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue
max :: PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue
$cmax :: PhoneNumberValue -> PhoneNumberValue -> PhoneNumberValue
>= :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c>= :: PhoneNumberValue -> PhoneNumberValue -> Bool
> :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c> :: PhoneNumberValue -> PhoneNumberValue -> Bool
<= :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c<= :: PhoneNumberValue -> PhoneNumberValue -> Bool
< :: PhoneNumberValue -> PhoneNumberValue -> Bool
$c< :: PhoneNumberValue -> PhoneNumberValue -> Bool
compare :: PhoneNumberValue -> PhoneNumberValue -> Ordering
$ccompare :: PhoneNumberValue -> PhoneNumberValue -> Ordering
$cp1Ord :: Eq PhoneNumberValue
Ord, Int -> PhoneNumberValue -> ShowS
[PhoneNumberValue] -> ShowS
PhoneNumberValue -> String
(Int -> PhoneNumberValue -> ShowS)
-> (PhoneNumberValue -> String)
-> ([PhoneNumberValue] -> ShowS)
-> Show PhoneNumberValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PhoneNumberValue] -> ShowS
$cshowList :: [PhoneNumberValue] -> ShowS
show :: PhoneNumberValue -> String
$cshow :: PhoneNumberValue -> String
showsPrec :: Int -> PhoneNumberValue -> ShowS
$cshowsPrec :: Int -> PhoneNumberValue -> ShowS
Show)

instance ToJSON PhoneNumberValue where
  toJSON :: PhoneNumberValue -> Value
toJSON (PhoneNumberValue Text
value) = [Pair] -> Value
object
    [ Text
"value" Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
value
    , Text
"type"  Text -> Text -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= (Text
"value" :: Text)
    ]