{-|
Module      : Gargantext.API.Node.Types
Description :
Copyright   : (c) CNRS, 2017
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX
-}

{-# LANGUAGE TemplateHaskell    #-}

module Gargantext.API.Node.Types where

import Control.Lens hiding (elements, Empty)
import Data.Aeson
import Data.ByteString qualified as BS
import Data.ByteString.Base64 qualified as BSB64
import Data.Swagger
import Data.Text qualified as T
import Gargantext.API.Node.Corpus.New.Types (FileType, FileFormat)
import Gargantext.API.Node.Corpus.Types
import Gargantext.Core (Lang(..))
import Gargantext.Core.Text.Corpus.Query qualified as API
import Gargantext.Core.Text.List.Social (FlowSocialListWith)
import Gargantext.Core.Types (NodeId)
import Gargantext.Core.Utils.Prefix (unPrefix)
import Gargantext.Core.Utils.Prefix (unPrefixSwagger)
import Gargantext.Database.GargDB qualified as GargDB
import Gargantext.Prelude
import Servant.Job.Utils (jsonOptions)
import Test.QuickCheck
import Web.FormUrlEncoded          (FromForm, ToForm)

-------------------------------------------------------
data NewWithForm = NewWithForm
  { _wf_filetype   :: !FileType
  , _wf_fileformat :: !FileFormat
  , _wf_data       :: !Text    -- NOTE for binary files, this represents base-64 data
  , _wf_lang       :: !(Maybe Lang)
  , _wf_name       :: !Text
  , _wf_selection  :: !FlowSocialListWith
  } deriving (Eq, Show, Generic)

makeLenses ''NewWithForm
instance FromForm NewWithForm
instance ToForm NewWithForm
instance FromJSON NewWithForm where
  parseJSON = genericParseJSON $ jsonOptions "_wf_"
instance ToJSON NewWithForm where
  toJSON = genericToJSON $ jsonOptions "_wf_"
instance ToSchema NewWithForm where
  declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_wf_")

-------------------------------------------------------

data NewWithFile = NewWithFile
  { _wfi_b64_data  :: !Text
  , _wfi_lang      :: !(Maybe Lang)
  , _wfi_name      :: !Text
  } deriving (Eq, Show, Generic)

makeLenses ''NewWithFile
instance FromForm NewWithFile
instance ToForm NewWithFile
instance FromJSON NewWithFile where
  parseJSON = genericParseJSON $ jsonOptions "_wfi_"
instance ToJSON NewWithFile where
  toJSON = genericToJSON $ jsonOptions "_wfi_"


instance ToSchema NewWithFile where
  declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_wfi_")

instance GargDB.SaveFile NewWithFile where
  saveFile' fp (NewWithFile b64d _ _) = do
    let eDecoded = BSB64.decode $ encodeUtf8 b64d
    case eDecoded of
      Left err -> panicTrace $ T.pack $ "Error decoding: " <> err
      Right decoded -> BS.writeFile fp decoded
    -- BS.writeFile fp $ BSB64.decodeLenient $ TE.encodeUtf8 b64d

--instance GargDB.ReadFile NewWithFile where
--  readFile' = TIO.readFile

data WithQuery = WithQuery
  { _wq_query        :: !API.RawQuery
  , _wq_databases    :: !Database
  , _wq_datafield    :: !(Maybe Datafield)
  , _wq_lang         :: !Lang
  , _wq_node_id      :: !Int
  , _wq_flowListWith :: !FlowSocialListWith
  , _wq_pubmedAPIKey :: !(Maybe Text)
  , _wq_epoAPIUser   :: !(Maybe Text)
  , _wq_epoAPIToken  :: !(Maybe Text)
  }
  deriving (Show, Eq, Generic)

makeLenses ''WithQuery
instance FromJSON WithQuery where
  parseJSON = genericParseJSON $ jsonOptions "_wq_"
instance ToJSON WithQuery where
  toJSON = genericToJSON $ jsonOptions "_wq_"
instance ToSchema WithQuery where
  declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_wq_")

instance Arbitrary WithQuery where
  arbitrary = WithQuery <$> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary
                        <*> arbitrary

------------------------------------------------------------------------
data RenameNode = RenameNode { r_name :: Text }
  deriving (Generic)

$(deriveJSON (unPrefix "r_"       ) ''RenameNode )
instance ToSchema  RenameNode
instance Arbitrary RenameNode where
  arbitrary = elements [RenameNode "test"]

data NodesToScore = NodesToScore { nts_nodesId :: [NodeId]
                                 , nts_score :: Int
                                 }
  deriving (Generic)

-- TODO unPrefix "ntc_" FromJSON, ToJSON, ToSchema, adapt frontend.
instance FromJSON  NodesToScore
instance ToJSON    NodesToScore
instance ToSchema  NodesToScore

data NodesToCategory = NodesToCategory { ntc_nodesId :: [NodeId]
                                       , ntc_category :: Int
                                       }
  deriving (Generic)

-- TODO unPrefix "ntc_" FromJSON, ToJSON, ToSchema, adapt frontend.
instance FromJSON  NodesToCategory
instance ToJSON    NodesToCategory
instance ToSchema  NodesToCategory

