{-|
This module contains CSV generator for the output.

-}

module Lsql.Csv.Utils.CsvGenerator(csvGenerate) where



import Lsql.Csv.Core.Tables
import Lsql.Csv.Core.Functions

import Data.List

-- | This function generates CSV output
csvGenerate :: Char -- ^ Primary delimiter 
            -> Char -- ^ Secondary delimiter (quote char)
            -> [Printable] -- ^ List of columns
            -> String  

csvGenerate :: Char -> Char -> [Printable] -> String
csvGenerate Char
sep Char
sec_sep [Printable]
cols =
  [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ ([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
genLine [[String]]
rows

  where
    
    rows :: [[String]]
    rows :: [[String]]
rows = [[String]] -> [[String]]
forall a. [[a]] -> [[a]]
transpose([[String]] -> [[String]]) -> [[String]] -> [[String]]
forall a b. (a -> b) -> a -> b
$ [Printable] -> [[String]]
genStrCols [Printable]
cols

    genLine :: [String] -> String
    genLine :: [String] -> String
genLine (String
a : String
b : [String]
rest) = String -> String
genCell String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
sep] String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
genLine (String
b String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
rest)
    genLine (String
a : [String]
_) = String -> String
genCell String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
'\n']

    genCell :: String -> String
    genCell :: String -> String
genCell String
input 
      | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
sep) String
input = String
quoted_input
      | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
sec_sep) String
input = String
quoted_input
      | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'\n') String
input = String
quoted_input

      | Bool
otherwise = String
input

      where 
        quoted_input :: String
        quoted_input :: String
quoted_input = [Char
sec_sep] String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String -> String
doubleSecSep String
input) String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
sec_sep]

        doubleSecSep :: String -> String
        doubleSecSep :: String -> String
doubleSecSep [] = []
        doubleSecSep (Char
a : String
rest)
          | Char
sec_sep Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
a = Char
sec_sep Char -> String -> String
forall a. a -> [a] -> [a]
: Char
sec_sep Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
doubleSecSep String
rest
          | Bool
otherwise = Char
a Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
doubleSecSep String
rest