{-|
Module      : Test.Database.Operations.PublishNode
Description : GarganText database tests
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX
-}

module Test.Database.Operations.PublishNode where

import Prelude

import Control.Monad.Reader
import Gargantext.Core
import Gargantext.Core.Types.Individu
import Gargantext.Database.Action.User (getUserId)
import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude
import Gargantext.Database.Query.Table.Node
import Gargantext.Database.Query.Table.NodeNode
import Gargantext.Database.Schema.Node (NodePoly(..))
import Test.API.Prelude (newPrivateFolderForUser, newPublicFolderForUser, alice)
import Test.Database.Types
import Test.HUnit

publishStrict :: SourceId -> TargetId -> DBCmd err ()
publishStrict sid = runDBTx . publishNode NPP_publish_no_edits_allowed sid

publishLenient :: SourceId -> TargetId -> DBCmd err ()
publishLenient sid = runDBTx . publishNode NPP_publish_edits_only_owner_or_super sid

testGetUserRootPublicNode :: TestEnv -> Assertion
testGetUserRootPublicNode testEnv = do
  alicePublicFolder <- runTestMonad testEnv $ runDBQuery $ do
    aliceId <- getUserId (UserName "alice")
    getUserRootPublicNode aliceId
  _node_typename alicePublicFolder @?= (toDBid NodeFolderPublic)

testIsReadOnlyWorks :: TestEnv -> Assertion
testIsReadOnlyWorks testEnv = do
  alicePrivateFolderId <- newPrivateFolderForUser testEnv alice
  alicePublicFolderId  <- newPublicFolderForUser testEnv alice
  runTestMonad testEnv $ do
    -- Create a corpus, by default is not read only
    aliceUserId <- runDBQuery $ getUserId (UserName "alice")
    corpusId    <- runDBTx $ insertDefaultNode NodeCorpus alicePrivateFolderId aliceUserId

    runDBQuery (isNodeReadOnly corpusId) >>= liftIO . (@?= False)

    -- Publish the node, then check that's now public.
    publishStrict (SourceId corpusId) (TargetId alicePublicFolderId)
    runDBQuery (isNodeReadOnly corpusId) >>= liftIO . (@?= True)

    -- Finally check that if we unpublish, the node is back to normal
    runDBTx $ unpublishNode (SourceId corpusId) (TargetId alicePublicFolderId)
    runDBQuery (isNodeReadOnly corpusId) >>= liftIO . (@?= False)

-- | In this test, we check that if we publish the root of a subtree,
-- then all the children (up to the first level) are also marked read-only.
testPublishRecursiveFirstLevel :: TestEnv -> Assertion
testPublishRecursiveFirstLevel testEnv = do
  alicePrivateFolderId <- newPrivateFolderForUser testEnv alice
  alicePublicFolderId  <- newPublicFolderForUser testEnv alice
  runTestMonad testEnv $ do
    -- Create a corpus, by default is not read only
    aliceUserId    <- runDBQuery $ getUserId (UserName "alice")
    aliceFolderId  <- runDBTx $ insertDefaultNode NodeFolder alicePrivateFolderId aliceUserId
    corpusId       <- runDBTx $ insertDefaultNode NodeCorpus aliceFolderId aliceUserId

    publishStrict (SourceId aliceFolderId) (TargetId alicePublicFolderId)

    runDBQuery (isNodeReadOnly aliceFolderId) >>= liftIO . (@?= True)
    runDBQuery (isNodeReadOnly corpusId)      >>= liftIO . (@?= True)

-- | In this test, we check that if we publish the root of a subtree,
-- then all the children of the children are also marked read-only.
testPublishRecursiveNLevel :: TestEnv -> Assertion
testPublishRecursiveNLevel testEnv = do
  alicePrivateFolderId <- newPrivateFolderForUser testEnv alice
  alicePublicFolderId  <- newPublicFolderForUser testEnv alice
  runTestMonad testEnv $ do
    -- Create a corpus, by default is not read only
    aliceUserId    <- runDBQuery $ getUserId (UserName "alice")
    aliceFolderId  <- runDBTx $ insertDefaultNode NodeFolder alicePrivateFolderId aliceUserId
    aliceSubFolderId <- runDBTx $ insertDefaultNode NodeFolder aliceFolderId aliceUserId
    corpusId       <- runDBTx $ insertDefaultNode NodeCorpus aliceSubFolderId aliceUserId

    publishStrict (SourceId aliceFolderId) (TargetId alicePublicFolderId)

    runDBQuery (isNodeReadOnly aliceFolderId)    >>= liftIO . (@?= True)
    runDBQuery (isNodeReadOnly aliceSubFolderId) >>= liftIO . (@?= True)
    runDBQuery (isNodeReadOnly corpusId)         >>= liftIO . (@?= True)

testPublishLenientWorks :: TestEnv -> Assertion
testPublishLenientWorks testEnv = do
  alicePrivateFolderId <- newPrivateFolderForUser testEnv alice
  alicePublicFolderId  <- newPublicFolderForUser testEnv alice
  runTestMonad testEnv $ do
    aliceUserId <- runDBQuery $ getUserId (UserName "alice")
    corpusId    <- runDBTx $ insertDefaultNode NodeCorpus alicePrivateFolderId aliceUserId
    publishLenient (SourceId corpusId) (TargetId alicePublicFolderId)
    runDBQuery (isNodeReadOnly corpusId) >>= liftIO . (@?= True)