{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
module Data.Connect.BaseTypes
   ( Key(..)
   , PluginKey(..)
   , Timeout(..)
   , Vendor(..)
   , Authentication(..)
   , AuthType(..)
   , IconDetails(..)
   , Name(..)
   , I18nText(..)
   , simpleText
   , URLBean(..)
   , toUrl
   , Length(..)
   )
   where

import qualified Data.Aeson                   as DA
import qualified Data.Aeson.Types             as DAT
import           Data.Connect.AesonHelpers
import           Data.Connect.OrphanInstances ()
import           Data.Text
import qualified Data.Time.Units              as DTU
import           GHC.Generics
import qualified Network.URI                  as NU

-- | This data type represents a Key for a particular data type.
data Key t a = Key t deriving (Int -> Key t a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall t a. Show t => Int -> Key t a -> ShowS
forall t a. Show t => [Key t a] -> ShowS
forall t a. Show t => Key t a -> String
showList :: [Key t a] -> ShowS
$cshowList :: forall t a. Show t => [Key t a] -> ShowS
show :: Key t a -> String
$cshow :: forall t a. Show t => Key t a -> String
showsPrec :: Int -> Key t a -> ShowS
$cshowsPrec :: forall t a. Show t => Int -> Key t a -> ShowS
Show, Key t a -> Key t a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall t a. Eq t => Key t a -> Key t a -> Bool
/= :: Key t a -> Key t a -> Bool
$c/= :: forall t a. Eq t => Key t a -> Key t a -> Bool
== :: Key t a -> Key t a -> Bool
$c== :: forall t a. Eq t => Key t a -> Key t a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall t a x. Rep (Key t a) x -> Key t a
forall t a x. Key t a -> Rep (Key t a) x
$cto :: forall t a x. Rep (Key t a) x -> Key t a
$cfrom :: forall t a x. Key t a -> Rep (Key t a) x
Generic)

-- | This data type represents an Atlassian Connect Add-on key.
data PluginKey = PluginKey Text deriving (Int -> PluginKey -> ShowS
[PluginKey] -> ShowS
PluginKey -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PluginKey] -> ShowS
$cshowList :: [PluginKey] -> ShowS
show :: PluginKey -> String
$cshow :: PluginKey -> String
showsPrec :: Int -> PluginKey -> ShowS
$cshowsPrec :: Int -> PluginKey -> ShowS
Show, PluginKey -> PluginKey -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PluginKey -> PluginKey -> Bool
$c/= :: PluginKey -> PluginKey -> Bool
== :: PluginKey -> PluginKey -> Bool
$c== :: PluginKey -> PluginKey -> Bool
Eq, forall x. Rep PluginKey x -> PluginKey
forall x. PluginKey -> Rep PluginKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PluginKey x -> PluginKey
$cfrom :: forall x. PluginKey -> Rep PluginKey x
Generic)

instance DA.ToJSON PluginKey

-- | Represents a timeout in seconds.
newtype Timeout = Timeout DTU.Second deriving (Int -> Timeout -> ShowS
[Timeout] -> ShowS
Timeout -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Timeout] -> ShowS
$cshowList :: [Timeout] -> ShowS
show :: Timeout -> String
$cshow :: Timeout -> String
showsPrec :: Int -> Timeout -> ShowS
$cshowsPrec :: Int -> Timeout -> ShowS
Show, Timeout -> Timeout -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Timeout -> Timeout -> Bool
$c/= :: Timeout -> Timeout -> Bool
== :: Timeout -> Timeout -> Bool
$c== :: Timeout -> Timeout -> Bool
Eq, Int -> Timeout
Timeout -> Int
Timeout -> [Timeout]
Timeout -> Timeout
Timeout -> Timeout -> [Timeout]
Timeout -> Timeout -> Timeout -> [Timeout]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Timeout -> Timeout -> Timeout -> [Timeout]
$cenumFromThenTo :: Timeout -> Timeout -> Timeout -> [Timeout]
enumFromTo :: Timeout -> Timeout -> [Timeout]
$cenumFromTo :: Timeout -> Timeout -> [Timeout]
enumFromThen :: Timeout -> Timeout -> [Timeout]
$cenumFromThen :: Timeout -> Timeout -> [Timeout]
enumFrom :: Timeout -> [Timeout]
$cenumFrom :: Timeout -> [Timeout]
fromEnum :: Timeout -> Int
$cfromEnum :: Timeout -> Int
toEnum :: Int -> Timeout
$ctoEnum :: Int -> Timeout
pred :: Timeout -> Timeout
$cpred :: Timeout -> Timeout
succ :: Timeout -> Timeout
$csucc :: Timeout -> Timeout
Enum, Integer -> Timeout
Timeout -> Timeout
Timeout -> Timeout -> Timeout
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Timeout
$cfromInteger :: Integer -> Timeout
signum :: Timeout -> Timeout
$csignum :: Timeout -> Timeout
abs :: Timeout -> Timeout
$cabs :: Timeout -> Timeout
negate :: Timeout -> Timeout
$cnegate :: Timeout -> Timeout
* :: Timeout -> Timeout -> Timeout
$c* :: Timeout -> Timeout -> Timeout
- :: Timeout -> Timeout -> Timeout
$c- :: Timeout -> Timeout -> Timeout
+ :: Timeout -> Timeout -> Timeout
$c+ :: Timeout -> Timeout -> Timeout
Num, Eq Timeout
Timeout -> Timeout -> Bool
Timeout -> Timeout -> Ordering
Timeout -> Timeout -> Timeout
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 :: Timeout -> Timeout -> Timeout
$cmin :: Timeout -> Timeout -> Timeout
max :: Timeout -> Timeout -> Timeout
$cmax :: Timeout -> Timeout -> Timeout
>= :: Timeout -> Timeout -> Bool
$c>= :: Timeout -> Timeout -> Bool
> :: Timeout -> Timeout -> Bool
$c> :: Timeout -> Timeout -> Bool
<= :: Timeout -> Timeout -> Bool
$c<= :: Timeout -> Timeout -> Bool
< :: Timeout -> Timeout -> Bool
$c< :: Timeout -> Timeout -> Bool
compare :: Timeout -> Timeout -> Ordering
$ccompare :: Timeout -> Timeout -> Ordering
Ord, Num Timeout
Ord Timeout
Timeout -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Timeout -> Rational
$ctoRational :: Timeout -> Rational
Real, Enum Timeout
Real Timeout
Timeout -> Integer
Timeout -> Timeout -> (Timeout, Timeout)
Timeout -> Timeout -> Timeout
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: Timeout -> Integer
$ctoInteger :: Timeout -> Integer
divMod :: Timeout -> Timeout -> (Timeout, Timeout)
$cdivMod :: Timeout -> Timeout -> (Timeout, Timeout)
quotRem :: Timeout -> Timeout -> (Timeout, Timeout)
$cquotRem :: Timeout -> Timeout -> (Timeout, Timeout)
mod :: Timeout -> Timeout -> Timeout
$cmod :: Timeout -> Timeout -> Timeout
div :: Timeout -> Timeout -> Timeout
$cdiv :: Timeout -> Timeout -> Timeout
rem :: Timeout -> Timeout -> Timeout
$crem :: Timeout -> Timeout -> Timeout
quot :: Timeout -> Timeout -> Timeout
$cquot :: Timeout -> Timeout -> Timeout
Integral)

-- | Represents the Vendor of the add-on; which will be you. Put your details in this structure.
data Vendor = Vendor
   { Vendor -> Name Vendor
vendorName :: Name Vendor -- ^ Your name as a Vendor. Might be your personal name or your business name.
   , Vendor -> URI
vendorUrl :: NU.URI -- ^ A URL to a website that represents you as a vendor.
   } deriving (Int -> Vendor -> ShowS
[Vendor] -> ShowS
Vendor -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Vendor] -> ShowS
$cshowList :: [Vendor] -> ShowS
show :: Vendor -> String
$cshow :: Vendor -> String
showsPrec :: Int -> Vendor -> ShowS
$cshowsPrec :: Int -> Vendor -> ShowS
Show, Vendor -> Vendor -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Vendor -> Vendor -> Bool
$c/= :: Vendor -> Vendor -> Bool
== :: Vendor -> Vendor -> Bool
$c== :: Vendor -> Vendor -> Bool
Eq, forall x. Rep Vendor x -> Vendor
forall x. Vendor -> Rep Vendor x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Vendor x -> Vendor
$cfrom :: forall x. Vendor -> Rep Vendor x
Generic)

-- | If your Atlassian Connect addon wants to perform any server side communication with the host product then you will
-- need to use authentication. Otherwise you should specify that you don't need authentication.
data Authentication = Authentication
   { Authentication -> AuthType
authType :: AuthType -- ^ The authentication type that you wish to use.
   } deriving (Int -> Authentication -> ShowS
[Authentication] -> ShowS
Authentication -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Authentication] -> ShowS
$cshowList :: [Authentication] -> ShowS
show :: Authentication -> String
$cshow :: Authentication -> String
showsPrec :: Int -> Authentication -> ShowS
$cshowsPrec :: Int -> Authentication -> ShowS
Show, Authentication -> Authentication -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Authentication -> Authentication -> Bool
$c/= :: Authentication -> Authentication -> Bool
== :: Authentication -> Authentication -> Bool
$c== :: Authentication -> Authentication -> Bool
Eq, forall x. Rep Authentication x -> Authentication
forall x. Authentication -> Rep Authentication x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Authentication x -> Authentication
$cfrom :: forall x. Authentication -> Rep Authentication x
Generic)

-- | The authentication type that you wish to use in your Add-on.
data AuthType
   = Jwt -- ^ If you need to communicate with the host product then you will want to request JWT authentication.
   | None -- ^ If you do not need to communicate the host product then you should request None for authentication.
   deriving (Int -> AuthType -> ShowS
[AuthType] -> ShowS
AuthType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AuthType] -> ShowS
$cshowList :: [AuthType] -> ShowS
show :: AuthType -> String
$cshow :: AuthType -> String
showsPrec :: Int -> AuthType -> ShowS
$cshowsPrec :: Int -> AuthType -> ShowS
Show, AuthType -> AuthType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AuthType -> AuthType -> Bool
$c/= :: AuthType -> AuthType -> Bool
== :: AuthType -> AuthType -> Bool
$c== :: AuthType -> AuthType -> Bool
Eq, forall x. Rep AuthType x -> AuthType
forall x. AuthType -> Rep AuthType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AuthType x -> AuthType
$cfrom :: forall x. AuthType -> Rep AuthType x
Generic)

-- | Represents an arbitrary icon. Potentially for an Atlassian Connect module or for the entire add-on itself.
data IconDetails = IconDetails
   { IconDetails -> Text
iconUrl    :: Text -- ^ The URI to the icon.
   , IconDetails -> Maybe Integer
iconWidth  :: Maybe Integer -- ^ The width of the icon.
   , IconDetails -> Maybe Integer
iconHeight :: Maybe Integer -- ^ The height of the icon.
   } deriving (Int -> IconDetails -> ShowS
[IconDetails] -> ShowS
IconDetails -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IconDetails] -> ShowS
$cshowList :: [IconDetails] -> ShowS
show :: IconDetails -> String
$cshow :: IconDetails -> String
showsPrec :: Int -> IconDetails -> ShowS
$cshowsPrec :: Int -> IconDetails -> ShowS
Show, forall x. Rep IconDetails x -> IconDetails
forall x. IconDetails -> Rep IconDetails x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep IconDetails x -> IconDetails
$cfrom :: forall x. IconDetails -> Rep IconDetails x
Generic)

-- | Atlassian Connect descriptors contain many names: module names, add-on names, vendor names etc. We want to make sure
-- that these names don't get put in places that they do not belong. Or, if they do get moved around, they get moved around
-- specifically. We are just adding type saefty to names.
data Name a = Name Text deriving (Int -> Name a -> ShowS
forall a. Int -> Name a -> ShowS
forall a. [Name a] -> ShowS
forall a. Name a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Name a] -> ShowS
$cshowList :: forall a. [Name a] -> ShowS
show :: Name a -> String
$cshow :: forall a. Name a -> String
showsPrec :: Int -> Name a -> ShowS
$cshowsPrec :: forall a. Int -> Name a -> ShowS
Show, Name a -> Name a -> Bool
forall a. Name a -> Name a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Name a -> Name a -> Bool
$c/= :: forall a. Name a -> Name a -> Bool
== :: Name a -> Name a -> Bool
$c== :: forall a. Name a -> Name a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Name a) x -> Name a
forall a x. Name a -> Rep (Name a) x
$cto :: forall a x. Rep (Name a) x -> Name a
$cfrom :: forall a x. Name a -> Rep (Name a) x
Generic)

-- | Represents a standard text type in the descriptor than may be Internationalised in the future. However, currently
-- there is no I18n support: <http://goo.gl/9vJEsW>
data I18nText = I18nText
   { I18nText -> Text
dValue :: Text -- ^ The raw text value that will show.
   , I18nText -> Maybe Text
dI18n  :: Maybe Text -- ^ The potential i18n key that will be used when we eventually have I18n support: <http://goo.gl/9vJEsW>
   } deriving (Int -> I18nText -> ShowS
[I18nText] -> ShowS
I18nText -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [I18nText] -> ShowS
$cshowList :: [I18nText] -> ShowS
show :: I18nText -> String
$cshow :: I18nText -> String
showsPrec :: Int -> I18nText -> ShowS
$cshowsPrec :: Int -> I18nText -> ShowS
Show, forall x. Rep I18nText x -> I18nText
forall x. I18nText -> Rep I18nText x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep I18nText x -> I18nText
$cfrom :: forall x. I18nText -> Rep I18nText x
Generic)

instance DA.ToJSON I18nText where
   toJSON :: I18nText -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
DAT.genericToJSON Options
baseOptions
      { fieldLabelModifier :: ShowS
DA.fieldLabelModifier = String -> ShowS
stripFieldNamePrefix String
"d"
      }

-- | Since there is currently no I18n support (<http://goo.gl/9vJEsW>) we have this helper method to quickly create an 'I18nText' from a standard
-- 'Text' object.
simpleText :: Text -> I18nText
simpleText :: Text -> I18nText
simpleText Text
t = I18nText { dValue :: Text
dValue = Text
t, dI18n :: Maybe Text
dI18n = forall a. Maybe a
Nothing }

-- | This represents a URL wrapped as an object instead of as a plain text element.
data URLBean = URLBean
   { URLBean -> Text
ubUrl :: Text -- ^ The raw URL.
   } deriving (Int -> URLBean -> ShowS
[URLBean] -> ShowS
URLBean -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [URLBean] -> ShowS
$cshowList :: [URLBean] -> ShowS
show :: URLBean -> String
$cshow :: URLBean -> String
showsPrec :: Int -> URLBean -> ShowS
$cshowsPrec :: Int -> URLBean -> ShowS
Show, forall x. Rep URLBean x -> URLBean
forall x. URLBean -> Rep URLBean x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep URLBean x -> URLBean
$cfrom :: forall x. URLBean -> Rep URLBean x
Generic)

instance DA.ToJSON URLBean where
   toJSON :: URLBean -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
DAT.genericToJSON Options
baseOptions
         { fieldLabelModifier :: ShowS
DA.fieldLabelModifier = String -> ShowS
stripFieldNamePrefix String
"ub"
         }

-- | Wrap a regular 'Text' based URL inside a URLBean.
toUrl :: Text -> URLBean
toUrl :: Text -> URLBean
toUrl = Text -> URLBean
URLBean

instance DA.ToJSON (Name PluginKey)
instance DA.ToJSON (Name Vendor)

instance DA.ToJSON IconDetails where
   toJSON :: IconDetails -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
DAT.genericToJSON Options
baseOptions
      { fieldLabelModifier :: ShowS
DA.fieldLabelModifier = String -> ShowS
stripFieldNamePrefix String
"icon"
      }

instance DA.ToJSON Vendor where
   toJSON :: Vendor -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
DAT.genericToJSON Options
baseOptions
      { fieldLabelModifier :: ShowS
DA.fieldLabelModifier = String -> ShowS
stripFieldNamePrefix String
"vendor"
      }

instance DA.ToJSON Authentication where
   toJSON :: Authentication -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
DAT.genericToJSON Options
baseOptions
      { fieldLabelModifier :: ShowS
DA.fieldLabelModifier = String -> ShowS
stripFieldNamePrefix String
"auth"
      }

instance DA.ToJSON AuthType where
   toJSON :: AuthType -> Value
toJSON AuthType
Jwt  = Value
"jwt"
   toJSON AuthType
None  = Value
"none"

-- | A basic length type for HTML elements. Useful for 'WebPanel's and other modules that may require length specifications.
data Length
   = Pixels Integer -- ^ Specify a length in pixels
   | Percentage Integer -- ^ Specify a length as a percentage in the range [0-100].
   deriving (Int -> Length -> ShowS
[Length] -> ShowS
Length -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Length] -> ShowS
$cshowList :: [Length] -> ShowS
show :: Length -> String
$cshow :: Length -> String
showsPrec :: Int -> Length -> ShowS
$cshowsPrec :: Int -> Length -> ShowS
Show, forall x. Rep Length x -> Length
forall x. Length -> Rep Length x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Length x -> Length
$cfrom :: forall x. Length -> Rep Length x
Generic)

instance DA.ToJSON Length where
   toJSON :: Length -> Value
toJSON (Pixels Integer
x) = Text -> Value
DAT.String forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack forall a b. (a -> b) -> a -> b
$ (forall a. Show a => a -> String
show Integer
x forall a. [a] -> [a] -> [a]
++ String
"px")
   toJSON (Percentage Integer
x) = Text -> Value
DAT.String forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack forall a b. (a -> b) -> a -> b
$ (forall a. Show a => a -> String
show Integer
x forall a. [a] -> [a] -> [a]
++ String
"%")