-- SPDX-FileCopyrightText: 2026 Alexandra de Wit
--
-- SPDX-License-Identifier: MIT

-- | Compact Simple indexes keep original file coordinates independently of retained order.
module Ecluse.Core.Registry.PyPI.Document (
    SimpleDocument,
    simpleDocument,
    simpleEnvelope,
    simpleFiles,
    simpleEncoding,
) where

import Data.Aeson (Encoding, Object, Value, toEncoding)
import Data.Aeson.Encoding qualified as Encoding
import Data.Aeson.KeyMap qualified as KeyMap

import Ecluse.Core.Package.Entry (EntryKey)

-- | Supported envelope fields and files associated with their original source positions.
data SimpleDocument = SimpleDocument
    { SimpleDocument -> Object
simpleEnvelope :: Object
    -- ^ Supported top-level fields, excluding the file array.
    , SimpleDocument -> [(EntryKey, Value)]
simpleFiles :: [(EntryKey, Value)]
    -- ^ Original keys in source order, including gaps left by discarded files.
    }
    deriving stock (SimpleDocument -> SimpleDocument -> Bool
(SimpleDocument -> SimpleDocument -> Bool)
-> (SimpleDocument -> SimpleDocument -> Bool) -> Eq SimpleDocument
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SimpleDocument -> SimpleDocument -> Bool
== :: SimpleDocument -> SimpleDocument -> Bool
$c/= :: SimpleDocument -> SimpleDocument -> Bool
/= :: SimpleDocument -> SimpleDocument -> Bool
Eq, Int -> SimpleDocument -> ShowS
[SimpleDocument] -> ShowS
SimpleDocument -> String
(Int -> SimpleDocument -> ShowS)
-> (SimpleDocument -> String)
-> ([SimpleDocument] -> ShowS)
-> Show SimpleDocument
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SimpleDocument -> ShowS
showsPrec :: Int -> SimpleDocument -> ShowS
$cshow :: SimpleDocument -> String
show :: SimpleDocument -> String
$cshowList :: [SimpleDocument] -> ShowS
showList :: [SimpleDocument] -> ShowS
Show)

-- | Bind compact files to their source coordinates before admission or assembly.
simpleDocument :: Object -> [(EntryKey, Value)] -> SimpleDocument
simpleDocument :: Object -> [(EntryKey, Value)] -> SimpleDocument
simpleDocument Object
envelope = Object -> [(EntryKey, Value)] -> SimpleDocument
SimpleDocument (Key -> Object -> Object
forall v. Key -> KeyMap v -> KeyMap v
KeyMap.delete Key
"files" Object
envelope)

-- | Encode the envelope with the retained files in source order. Source coordinates stay internal.
simpleEncoding :: SimpleDocument -> Encoding
simpleEncoding :: SimpleDocument -> Encoding
simpleEncoding SimpleDocument
document =
    Series -> Encoding
Encoding.pairs ((Key -> Encoding -> Series) -> KeyMap Encoding -> Series
forall m a. Monoid m => (Key -> a -> m) -> KeyMap a -> m
KeyMap.foldMapWithKey Key -> Encoding -> Series
Encoding.pair (Key -> Encoding -> KeyMap Encoding -> KeyMap Encoding
forall v. Key -> v -> KeyMap v -> KeyMap v
KeyMap.insert Key
"files" Encoding
files (Value -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (Value -> Encoding) -> Object -> KeyMap Encoding
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SimpleDocument -> Object
simpleEnvelope SimpleDocument
document)))
  where
    files :: Encoding
files = ((EntryKey, Value) -> Encoding) -> [(EntryKey, Value)] -> Encoding
forall a. (a -> Encoding) -> [a] -> Encoding
Encoding.list (Value -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (Value -> Encoding)
-> ((EntryKey, Value) -> Value) -> (EntryKey, Value) -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EntryKey, Value) -> Value
forall a b. (a, b) -> b
snd) (SimpleDocument -> [(EntryKey, Value)]
simpleFiles SimpleDocument
document)