{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Gundeck.Instances
  (
  )
where

import Amazonka.Data
import Cassandra.CQL
import Data.Attoparsec.Text qualified as Parser
import Data.ByteString.Lazy qualified as Bytes
import Data.Id
import Data.Text.Encoding qualified as Text
import Data.UUID qualified as Uuid
import Gundeck.Aws.Arn (EndpointArn)
import Imports
import Wire.API.Push.V2

instance Cql Transport where
  ctype = Tagged IntColumn

  toCql GCM = CqlInt 0
  toCql APNS = CqlInt 1
  toCql APNSSandbox = CqlInt 2
  toCql APNSVoIP = CqlInt 3
  toCql APNSVoIPSandbox = CqlInt 4

  fromCql (CqlInt i) = case i of
    0 -> pure GCM
    1 -> pure APNS
    2 -> pure APNSSandbox
    3 -> pure APNSVoIP
    4 -> pure APNSVoIPSandbox
    n -> Left $ "unexpected transport: " ++ show n
  fromCql _ = Left "transport: int expected"

instance Cql ConnId where
  ctype = Tagged BlobColumn

  toCql (ConnId c) = CqlBlob (Bytes.fromStrict c)

  fromCql (CqlBlob b) = pure . ConnId $ Bytes.toStrict b
  fromCql _ = Left "ConnId: Blob expected"

instance Cql EndpointArn where
  ctype = Tagged TextColumn
  toCql = CqlText . toText
  fromCql (CqlText txt) = fromText txt
  fromCql _ = Left "EndpointArn: Text expected"

instance Cql Token where
  ctype = Tagged TextColumn
  toCql = CqlText . tokenText
  fromCql (CqlText txt) = Right (Token txt)
  fromCql _ = Left "Token: Text expected"

instance Cql AppName where
  ctype = Tagged TextColumn
  toCql = CqlText . appNameText
  fromCql (CqlText txt) = Right (AppName txt)
  fromCql _ = Left "App: Text expected"

instance ToText (Id a) where
  toText = Text.decodeUtf8 . Uuid.toASCIIBytes . toUUID

instance FromText (Id a) where
  fromText =
    Parser.parseOnly $
      Parser.take 36 >>= \txt ->
        txt
          & Text.encodeUtf8
          & Uuid.fromASCIIBytes
          & maybe (fail "Invalid UUID") (pure . Id)
