{-# OPTIONS_GHC -Wall -Werror #-}

{-# LANGUAGE NoGeneralizedNewtypeDeriving #-}
{-# LANGUAGE Safe                         #-}

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

-- |
-- Copyright  : (c) 2026 SPISE MISU ApS
-- License    : SSPL-1.0 OR AGPL-3.0-only
-- Maintainer : SPISE MISU <mail+hackage@spisemisu.com>
-- Stability  : experimental

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

module Internal.Utils
  ( -- * Files
    files
  , file
    -- * History
  , chits
  , chats
    -- * Helpers
  , combine
  , leftpad
  , index
  , split
  , linesOptNums
  )
where

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

import           Prelude hiding ( lines )
import qualified Prelude as Prelude

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

combine
  :: [ (String, String) ]
  -> [ String ]
combine :: [(String, String)] -> [String]
combine =
  ((String, String) -> String) -> [(String, String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map
  ( \ (String
x, String
y) ->
      if String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
x then
        String
y
      else
        String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
y
  )

leftpad
  :: Char
  -> Int
  -> [Char]
  -> [Char]
leftpad :: Char -> Int -> String -> String
leftpad Char
chr Int
rep String
cs =
  Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
rep Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
xs) Char
chr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
xs
  where
    xs :: String
xs = Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
rep String
cs

index
  :: Int
  -> Int
  -> String
index :: Int -> Int -> String
index Int
rep Int
idx =
  Char -> Int -> String -> String
leftpad Char
'0' Int
rep (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
idx

split
  :: Char
  ->  String
  -> [String]
split :: Char -> String -> [String]
split Char
sep String
str =
  case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
sep) String
str of
    [] -> []
    String
cs ->
      String
b String -> [String] -> [String]
forall a. a -> [a] -> [a]
: Char -> String -> [String]
split Char
sep String
bs
      where
        (String
b, String
bs) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
sep) String
cs

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

files
  :: String
  -> Bool
  -> [ String ]
  -> [ (String, String) ]
files :: String -> Bool -> [String] -> [(String, String)]
files String
prefix Bool
nums [String]
fs =
  String -> Bool -> Int -> [String] -> [(String, String)]
linesOptNums String
prefix Bool
nums Int
0 [String]
fs

file
  :: Bool
  -> String
  -> [ (String, String) ]
file :: Bool -> String -> [(String, String)]
file Bool
nums String
f =
  String -> Bool -> Int -> [String] -> [(String, String)]
linesOptNums [] Bool
nums Int
1 ([String] -> [(String, String)]) -> [String] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ String -> [String]
Prelude.lines String
f

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

chits
  :: Bool
  -> [ String ]
  -> [ (String, String) ]
chits :: Bool -> [String] -> [(String, String)]
chits Bool
nums [String]
fs =
  String -> Bool -> Int -> [String] -> [(String, String)]
linesOptNums [] Bool
nums Int
0 ([String] -> [(String, String)]) -> [String] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
reverse [String]
fs

chats
  :: Bool
  -> [ String ]
  -> [ (String, String) ]
chats :: Bool -> [String] -> [(String, String)]
chats Bool
nums [String]
fs =
  String -> Bool -> Int -> [String] -> [(String, String)]
linesOptNums [] Bool
nums Int
0 ([String] -> [(String, String)]) -> [String] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [a] -> [a]
reverse [String]
fs

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

-- HELPERS (private)

linesOptNums
  :: String
  -> Bool
  -> Int
  -> [ String ]
  -> [ (String, String) ]
linesOptNums :: String -> Bool -> Int -> [String] -> [(String, String)]
linesOptNums String
prefix Bool
nums Int
origo [String]
xs =
  (Int -> String -> (String, String))
-> [Int] -> [String] -> [(String, String)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\ Int
idx String
rel -> (String
prefix String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
f Int
idx, String
rel)) [Int
origo..] [String]
xs
  where
    len :: Int
len   = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
xs
    f :: Int -> String
f Int
i =
      if Bool
nums then
        Int -> Int -> String
index Int
len Int
i
      else
        []