-- |
-- Module      :  Data.Lists.FLines
-- Copyright   :  (c) OleksandrZhabenko 2020
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- Additional data and structures to some 'String'-related lists.
--

{-# LANGUAGE CPP, FlexibleInstances, MultiParamTypeClasses #-}

module Data.Lists.FLines where

#ifdef __GLASGOW_HASKELL__
#if __GLASGOW_HASKELL__>=710
/* code that applies only to GHC 7.10.* and higher versions */
import GHC.Base (mconcat)
#endif
#endif
import System.IO

#ifdef __GLASGOW_HASKELL__
#if __GLASGOW_HASKELL__==708
/* code that applies only to GHC 7.8.* */
mconcat = concat
#endif
#endif


-- | Auxiliary printing function to define the line ending needed to be shown and printed. Is primarily defined in the @uniqueness-periods-vector-general@ package (https://hackage.haskell.org/package/uniqueness-periods-vector-general).
newLineEnding :: String
newLineEnding :: String
newLineEnding
  | Newline
nativeNewline Newline -> Newline -> Bool
forall a. Eq a => a -> a -> Bool
== Newline
LF = String
"\n"
  | Bool
otherwise = String
"\r\n"

data FLines a = F1 a | FL [a] deriving FLines a -> FLines a -> Bool
(FLines a -> FLines a -> Bool)
-> (FLines a -> FLines a -> Bool) -> Eq (FLines a)
forall a. Eq a => FLines a -> FLines a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FLines a -> FLines a -> Bool
$c/= :: forall a. Eq a => FLines a -> FLines a -> Bool
== :: FLines a -> FLines a -> Bool
$c== :: forall a. Eq a => FLines a -> FLines a -> Bool
Eq

type Flines = FLines String

-- | Is intended to be printed and so adds the new line ending.
instance Show (FLines String) where
  show :: FLines String -> String
show (F1 String
xs) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
xs, String
newLineEnding]
  show (FL (String
xs:[String]
xss)) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat (String
xsString -> [String] -> [String]
forall a. a -> [a] -> [a]
:String
newLineEndingString -> [String] -> [String]
forall a. a -> [a] -> [a]
:[FLines String -> String
forall a. Show a => a -> String
show ([String] -> FLines String
forall a. [a] -> FLines a
FL [String]
xss)])
  show FLines String
_ = String
newLineEnding

class GetN a b where
  getN :: Int -> a -> Maybe b

instance GetN (FLines String) String where
  getN :: Int -> FLines String -> Maybe String
getN Int
n (F1 String
xs)
    | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
xs = Maybe String
forall a. Maybe a
Nothing
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = String -> Maybe String
forall a. a -> Maybe a
Just String
xs
    | Bool
otherwise = Maybe String
forall a. Maybe a
Nothing
  getN Int
n (FL (String
xs:[String]
xss))
   | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
xs then Maybe String
forall a. Maybe a
Nothing else String -> Maybe String
forall a. a -> Maybe a
Just String
xs
   | Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
n Int
1 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
LT = Maybe String
forall a. Maybe a
Nothing
   | Bool
otherwise = Int -> FLines String -> Maybe String
forall a b. GetN a b => Int -> a -> Maybe b
getN (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ([String] -> FLines String
forall a. [a] -> FLines a
FL [String]
xss)
  getN Int
_ FLines String
_ = Maybe String
forall a. Maybe a
Nothing

class GetNTrans a b where
  getNT :: Int -> (b -> b) -> a -> Maybe b

instance GetNTrans (FLines String) String where
  getNT :: Int -> ShowS -> FLines String -> Maybe String
getNT Int
n ShowS
g (F1 String
xs)
    | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (ShowS
g String
xs) = Maybe String
forall a. Maybe a
Nothing
    | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1  = String -> Maybe String
forall a. a -> Maybe a
Just (ShowS
g String
xs)
    | Bool
otherwise = Maybe String
forall a. Maybe a
Nothing
  getNT Int
n ShowS
g (FL (String
xs:[String]
xss))
   | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (ShowS
g String
xs) then Maybe String
forall a. Maybe a
Nothing else String -> Maybe String
forall a. a -> Maybe a
Just (ShowS
g String
xs)
   | Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
n Int
1 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
LT = Maybe String
forall a. Maybe a
Nothing
   | Bool
otherwise = Int -> ShowS -> FLines String -> Maybe String
forall a b. GetNTrans a b => Int -> (b -> b) -> a -> Maybe b
getNT (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ShowS
g ([String] -> FLines String
forall a. [a] -> FLines a
FL [String]
xss)
  getNT Int
_ ShowS
_ FLines String
_ = Maybe String
forall a. Maybe a
Nothing

class GetTransL a b where
  getTL :: (b -> b) -> a -> b