{-|
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 (genericParseJSON, genericToJSON)
import Data.ByteString qualified as BS
import Data.ByteString.Base64 qualified as BSB64
import Data.Swagger (ToSchema(..), genericDeclareNamedSchema)
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.Aeson (jsonOptions)
import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger)
import Gargantext.Database.GargDB qualified as GargDB
import Gargantext.Prelude
import Web.FormUrlEncoded (FromForm, ToForm)

-------------------------------------------------------
-- | A file is uploaded with this type. Then, for internal job
-- creation for the worker, 'NewWithTempFile' is used with a large
-- object oid
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 NewWithTempFile = NewWithTempFile
  { _wtf_filetype   :: !FileType
  , _wtf_fileformat :: !FileFormat
  , _wtf_file_oid   :: !Int
  , _wtf_lang       :: !(Maybe Lang)
  , _wtf_name       :: !Text
  , _wtf_selection  :: !FlowSocialListWith
  } deriving (Eq, Show, Generic)

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

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

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_datafield    :: !Datafield
  , _wq_lang         :: !Lang
  , _wq_node_id      :: !Int
  , _wq_flowListWith :: !FlowSocialListWith
  }
  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_")

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

$(deriveJSON (unPrefix "r_"       ) ''RenameNode )
instance ToSchema  RenameNode

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

