-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Ability to read, write, and modify BBDB files
--   
--   BBDB (http:/<i>savannah.nongnu.org</i>projects<i>bbdb</i>) is a
--   contact management utility that can be used with emacs. It stores its
--   data internally as a lisp expression. This module parses the lisp and
--   provides some convenience functions to get at and manipulate the data
--   all from within Haskell. See the hackage docs for usage and examples.
@package bbdb
@version 0.8


-- | This module can read and write BBDB files, and provides a few handy
--   functions for getting at fields inside of BBDB data.
--   
--   BBDB (now version 3)
--   (<a>http://savannah.nongnu.org/projects/bbdb/</a>) is short for the
--   Insidious Big Brother Database, which is a contact management utility
--   that can be integrated into Emacs (the one true editor.) Since bbdb.el
--   is implemented in elisp, it can be difficult to "get at" the data
--   inside a .bbdb file with external programs. Many years ago, I wrote a
--   BBDB interface for perl, but having experience enlightenment at the
--   hands of the category gods, I`m now dabbling with Haskell. But having
--   been a loyal Emacs user for many years now, I wanted a way to spam my
--   friends while still using my favorite programming language. Hence the
--   module Data.BBDB.
--   
--   The following is the data layout for a BBDB record. I have created a
--   sample record with my own data. Each field is just separated by a
--   space. I have added comments to the right
--   
--   <pre>
--   ["Henry"                                   The first name - a string
--   "Laxen"                                    The last name - a string
--   nil                                        Affixes - a comma separated list
--   ("Henry, Enrique")                         Also Known As - a comma separated list
--   ("Elegant Solutions")                      Organizations- a comma separated list
--   (
--    ["reno" 775 624 1851 0]                   Phone number field - US style
--    ["chapala" "011-52-376-765-3181"]         Phone number field - International style
--   ) 
--   (
--    ["mailing"                                The address location, then a list
--    ("10580 N. McCarran Blvd." "#115-396")    for the street address, then one each
--    "Reno" "Nevada" "89503" "USA"             for City, State, Zip Code, and country
--   ] 
--    ["home"                                   another Address field
--    ("Villa Alta #6" "Gaviotas #10")            The street list
--    "Chapala" "Jalisco"                       City State
--    "45900" "Mexico"                          Zip and country
--   ]) 
--   (
--    "nadine.and.henry@pobox.com"              the net addresses - a list of strings
--    "nadinelaxen@pobox.com"
--   ) 
--   (
--    (notes . "Always split aces and eights")  The notes field - a list of alists
--    (birthday . "6/15")
--   )
--   "169cc701-8754-45f5-aba8-c89c2dc60a49"     The hash field based
--                                              on names, organizations, akas, and emails
--   "2010-09-03"                               The creation date
--   "2017-11-06 13:58:33 +0000"                The last modifcation time
--   nil                                        The cache vector - always nil
--   ]
--   </pre>
--   
--   Inside the .bbdb file, this looks like: ["Henry" "Laxen" nil ("Henry,
--   Enrique") ("Elegant Solutions") (["reno" 775 624 1851 0] ["chapala"
--   "011-52-376-765-3181"]) (["mailing" ("10580 N. McCarran Blvd."
--   "#115-396") "Reno" "Nevada" "89503" "USA"] ["home" ("Via Alta 10")
--   "Chapala" "Jalisco" "45900" "Mexico"]) ("nadine.and.henry@pobox.com"
--   "nadinelaxen@pobox.com") ((notes . "Always split aces and eights")
--   (birthday . "6/15")) "169cc701-8754-45f5-aba8-c89c2dc60a49"
--   "2010-09-03" "2017-11-06 13:58:33 +0000" nil]
--   
--   When parsed, this is represented inside Haskell as:
--   
--   <pre>
--   BBDBEntry
--     (BBDB{firstName = Just "Henry", lastName = Just "Laxen",
--           affix = Nothing
--           aka = Just ["Henry, Enrique"], company = Just ["Elegant Solutions"],
--           phone =
--             Just
--               [USStyle "reno" ["775", "624", "1851", "0"],
--                InternationalStyle "chapala" "011-52-376-765-3181"],
--           address =
--             Just
--               [Address{location = "mailing",
--                        streets =
--                          Just ["10580 N. McCarran Blvd.", "#115-396"],
--                        city = Just "Reno", state = Just "Nevada",
--                        zipcode = Just "89503", country = Just "USA"},
--                Address{location = "home",
--                        streets = Just ["Via Alta #6", "Gaviotas #10"],
--                        city = Just "Chapala", state = Just "Jalisco",
--                        zipcode = Just "45900", country = Just "Mexico"}],
--           net = Just ["nadine.and.henry@pobox.com", "nadinelaxen@pobox.com"],
--           notes =
--             Just
--               (Note{unnote =
--                       [("notes", "Always split aces and eights"),
--                        ("birthday", "6/15")]})})]
--          hash = "169cc701-8754-45f5-aba8-c89c2dc60a49",
--          creation = "2010-09-03",  
--          modification = "2017-11-06 13:58:33 +0000" 
--   </pre>
module Database.BBDB

-- | A Location is just a synonym for String. Each BBDB Address and Phone
--   field must be associated with a location, such as <i>home</i> or
--   <i>work</i>
type Location = String

-- | A Street is also a synonym for String. Each Address may have a list of
--   Streets associated with it.
type Street = String

-- | A Symbol is just a String, but Lisp only wants alphanumerics and the
--   characters _ (underscore) and - (dash)
type Symbol = String

-- | An Address must have a location, and may have associated streets, a
--   city, a state, a zipcode, and an country.
data Address
Address :: Location -> Maybe [String] -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Address
[location] :: Address -> Location
[streets] :: Address -> Maybe [String]
[city] :: Address -> Maybe String
[state] :: Address -> Maybe String
[zipcode] :: Address -> Maybe String
[country] :: Address -> Maybe String

-- | An Alist is an Association List. Lisp writes these as (key . value) We
--   convert these to a tuple in haskell where fst is key and snd is value.
type Alist = (Symbol, String)

-- | The Note field of a BBDB record is just a list of associations. If you
--   don't provide a your own key, the BBDB will use the word "note"
data Note
Note :: [Alist] -> Note
[unnote] :: Note -> [Alist]

-- | For some unknow reason, BBDB can have phones in two different formats.
--   In <i>USStyle</i>, the phone is list of integers, in the form of Area
--   code, Prefix, Number, and Extension. I don't bother to convert the
--   strings of digits to actual integers. In <i>InternationalStyle</i>,
--   the phone number is just a String.
data Phone
USStyle :: Location -> [String] -> Phone
InternationalStyle :: Location -> String -> Phone

-- | The record fields of the BBDB data type
data BBDB
BBDB :: Maybe String -> Maybe String -> Maybe [String] -> Maybe [String] -> Maybe [String] -> Maybe [Phone] -> Maybe [Address] -> Maybe [String] -> Maybe Note -> Hash -> CreationDate -> ModificationTime -> BBDB

-- | the first name. Why is this a Maybe? Because sometimes you just have a
--   company, and not a specific first name
[firstName] :: BBDB -> Maybe String
[lastName] :: BBDB -> Maybe String

-- | aka = Also Known As. Sometimes the same email address can match
--   several users, so BBDB gives you the option of remembering different
--   names for the same address
[affix] :: BBDB -> Maybe [String]
[aka] :: BBDB -> Maybe [String]

-- | The company if any
[company] :: BBDB -> Maybe [String]

-- | A list of phone numbers, either in US Style or International Style
[phone] :: BBDB -> Maybe [Phone]

-- | A list of addresses, keyed by location
[address] :: BBDB -> Maybe [Address]

-- | A list of email addresses. BBDB uses the first element of this field
--   when you create a new email
[net] :: BBDB -> Maybe [String]

-- | Any number of key, value pairs. Great for random data.
[notes] :: BBDB -> Maybe Note
[hash] :: BBDB -> Hash
[creation] :: BBDB -> CreationDate
[modification] :: BBDB -> ModificationTime

-- | At the beginning of a BBDB file are a variable number of comments,
--   which specify the encoding type and the version. We just ignore them.
--   Comments starts with a ; (semi-colon) and continue to end of line
data BBDBFile
BBDBComment :: String -> BBDBFile
BBDBEntry :: BBDB -> BBDBFile

-- | LispAble is how we convert from our internal representation of a BBDB
--   record, to one that will make Lisp and Emacs happy. (Sans bugs)
--   
--   <pre>
--   testInverse = do
--     let inFile = "/home/henry/.bbdb"
--     actualBBDBFile &lt;- readFile inFile
--     parsedBBDBdata &lt;- readBBDB inFile
--     let bbdbDataOut = asLisp parsedBBDBdata
--     print $ actualBBDBFile == bbdbDataOut
--    
--   </pre>
--   
--   should print True
class LispAble s
asLisp :: LispAble s => s -> String

-- | Since file-format 9, BBDB now includes there more fields, which | are
--   always present and used internally. | Synonym for String
type Hash = String

-- | Synonym for String
type CreationDate = String

-- | Synonym for String
type ModificationTime = String

-- | A BBDB record containing no data
bbdbDefault :: BBDB

-- | Given an Alist, return the key
key :: (x, y) -> x

-- | Given an Alist, return the value
value :: (x, y) -> y

-- | parse the string as a BBDB File
parseBBDB :: String -> Either ParseError [BBDBFile]

-- | The Parser for a BBDB file, as it is written on disk. If you read a
--   .bbdb file with:
--   
--   <pre>
--   testParse :: FilePath -&gt; IO (Either ParseError [BBDBFile])
--   testParse filename = do
--     b &lt;- readFile filename
--     return $  parse bbdbFileParse "bbdb" b
--   </pre>
--   
--   You will get IO (Right [BBDBFile]) if the parse went ok
bbdbFileParse :: Parser [BBDBFile]

-- | converts a BBDB comment to nothing, and a BBDB entry to just the entry
justEntry :: BBDBFile -> Maybe BBDB

-- | returns a list of only the actual bbdb entries, removing the comments
justEntries :: [BBDBFile] -> [BBDB]

-- | read the given file and call error if the parse failed, otherwise
--   return the entire file as a list of BBDBFile records.
readBBDB :: String -> IO [BBDBFile]

-- | Notes inside a BBDB record are awkward to get at. This helper function
--   digs into the record and applies a function to each Alist element of
--   the record. It returns true if it any of the Alists in the note return
--   true. For example:
--   
--   <pre>
--   hasBirthday :: BBDB -&gt; Bool
--   hasBirthday = wantNote (\x -&gt; key x == "birthday")
--   </pre>
--   
--   will return True for any BBDB record that has a "birthday" key in it's
--   notes field
wantNote :: (Alist -> Bool) -> BBDB -> Bool

-- | Lookup the value whose key is the given string. If found returns Just
--   the value, otherwise Nothing For example:
--   
--   <pre>
--   getBirthday :: BBDB -&gt; Maybe String
--   getBirthday = getNote "birthday"
--   </pre>
getNote :: String -> BBDB -> Maybe String

-- | This and filterBBDB are the main functions you should use to
--   manipulate a set of BBDB entries. You supply a function that applies a
--   transformation on a BBDB record, and this function will apply that
--   transformation to every BBDBEntry in a BBDB file. Sample usage:
--   
--   <pre>
--   starCompanies = do
--     b &lt;- readBBDB "/home/henry/.bbdb"
--     writeFile "/home/henry/.bbdb-new" $ asLisp . mapBBDB starCompany $ b
--     where
--       starCompany x = case (company x) of
--         Nothing -&gt; x
--         Just y -&gt; x { company = Just ("*" ++ y) }
--   </pre>
--   
--   Prepend a star ("*") to each company field of a BBDB file and write
--   the result out as a new bbdb file.
mapBBDB :: (BBDB -> BBDB) -> [BBDBFile] -> [BBDBFile]

-- | Just like mapBBDB except it filters. You supply a function that takes
--   a BBDB record to a Bool, and filterBBDB will return a new list of
--   BBDBFile that satisfy that condition. Sample usage:
--   
--   <pre>
--   import Text.Regex.Posix
--   -- do regex matching while ignoring case, so "reno" matches "Reno"
--   matches x = match (makeRegexOpts compIgnoreCase defaultExecOpt x :: Regex)
--   </pre>
--   
--   <pre>
--   getReno = do
--     b &lt;- readBBDB "/home/henry/.bbdb"
--     let c = justEntries . filterBBDB hasReno $ b
--     mapM_ print $ map (\a -&gt; (firstName a, lastName a, address a)) c
--     where
--       isReno :: Maybe String -&gt; Bool
--       isReno = maybe False (matches "reno")
--       anyAddressHasReno :: [Address] -&gt; Bool
--       anyAddressHasReno = any id . map (isReno . city)
--       hasReno :: BBDB -&gt; Bool
--       hasReno = maybe False anyAddressHasReno . address
--   </pre>
--   
--   print the name and all addresses of anyone in the BBDB file who live
--   in Reno.
filterBBDB :: (BBDB -> Bool) -> [BBDBFile] -> [BBDBFile]
instance GHC.Show.Show Database.BBDB.BBDBFile
instance GHC.Classes.Ord Database.BBDB.BBDBFile
instance GHC.Classes.Eq Database.BBDB.BBDBFile
instance GHC.Show.Show Database.BBDB.BBDB
instance GHC.Classes.Ord Database.BBDB.BBDB
instance GHC.Classes.Eq Database.BBDB.BBDB
instance GHC.Show.Show Database.BBDB.Note
instance GHC.Classes.Ord Database.BBDB.Note
instance GHC.Classes.Eq Database.BBDB.Note
instance GHC.Show.Show Database.BBDB.Address
instance GHC.Classes.Ord Database.BBDB.Address
instance GHC.Classes.Eq Database.BBDB.Address
instance GHC.Show.Show Database.BBDB.Phone
instance GHC.Classes.Ord Database.BBDB.Phone
instance GHC.Classes.Eq Database.BBDB.Phone
instance Database.BBDB.LispAble GHC.Base.String
instance Database.BBDB.LispAble (GHC.Maybe.Maybe GHC.Base.String)
instance Database.BBDB.LispAble (GHC.Maybe.Maybe [GHC.Base.String])
instance Database.BBDB.LispAble Database.BBDB.Phone
instance Database.BBDB.LispAble (GHC.Maybe.Maybe [Database.BBDB.Phone])
instance Database.BBDB.LispAble Database.BBDB.Address
instance Database.BBDB.LispAble (GHC.Maybe.Maybe [Database.BBDB.Address])
instance Database.BBDB.LispAble Database.BBDB.Alist
instance Database.BBDB.LispAble Database.BBDB.Note
instance Database.BBDB.LispAble (GHC.Maybe.Maybe Database.BBDB.Note)
instance Database.BBDB.LispAble Database.BBDB.BBDB
instance Database.BBDB.LispAble Database.BBDB.BBDBFile
instance Database.BBDB.LispAble [Database.BBDB.BBDBFile]
