content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE TemplateHaskellQuotes #-}
  
  -- | Internal module used for configuration purposes. You don't likely
  -- have to use it.
  module Config
    ( SourceData(..)
    , fetchData
    , fetchDataSingle
    , mapSource
    , populateLocales
    ) where
  
  import Control.Monad (filterM)
  import Control.Monad.Catch
  import Control.Monad.IO.Class
  import qualified Data.ByteString as BS
  import qualified Data.HashMap.Strict as HM
  import Data.Monoid ((<>))
  import Data.Text (Text, pack, unpack)
  import Data.Vector (Vector)
  import Data.Yaml
  import Faker
  import Faker.Internal.Types (CacheFileKey(..), SourceData(..))
  import Language.Haskell.TH (Name)
  import Paths_fakedata (getDataFileName)
  import System.Directory (doesFileExist, listDirectory)
  import System.FilePath ((<.>), (</>), takeExtension, takeFileName)
  
  localesDirectory :: FilePath
  localesDirectory = "faker/lib/locales"
  
  localesEnDirectory :: FilePath
  localesEnDirectory = "faker/lib/locales/en"
  
  localesCustomEnDirectory :: FilePath
  localesCustomEnDirectory = "customFakeSource/en"
  
  isLocaleFile :: FilePath -> IO Bool
  isLocaleFile fname = do
    exist <- doesFileExist fname
    pure (exist && (takeExtension fname == ".yml"))
  
  listLocaleFiles :: FilePath -> IO [FilePath]
  listLocaleFiles fname = do
    files <- listDirectory fname
    filterM isLocaleFile files
  
  populateLocales :: IO [Text]
  populateLocales = do
    files <- listLocaleFiles localesDirectory
    let files' = map (pack . takeFileName) files
    pure files'
  
  sourceFile :: SourceData -> FilePath
  sourceFile Address = "address"
  sourceFile Name = "name"
  sourceFile Ancient = "ancient"
  sourceFile Adjective = "adjective"
  sourceFile Animal = "animal"
  sourceFile App = "app"
  sourceFile Appliance = "appliance"
  sourceFile ATHF = "aqua_teen_hunger_force"
  sourceFile Artist = "artist"
  sourceFile BTTF = "back_to_the_future"
  sourceFile Bank = "bank"
  sourceFile Beer = "beer"
  sourceFile BoJackHorseman = "bojack_horseman"
  sourceFile Book = "book"
  sourceFile BossaNova = "bossa_nova"
  sourceFile BreakingBad = "breaking_bad"
  sourceFile Buffy = "buffy"
  sourceFile Business = "business"
  sourceFile Cannabis = "cannabis"
  sourceFile BigBangTheory = "big_bang_theory"
  sourceFile Cat = "cat"
  sourceFile ChuckNorris = "chuck_norris"
  sourceFile Code = "code"
  sourceFile Coffee = "coffee"
  sourceFile Coin = "coin"
  sourceFile Color = "color"
  sourceFile Horse = "horse"
  sourceFile Commerce = "commerce"
  sourceFile Community = "community"
  sourceFile Compass = "compass"
  sourceFile Company = "company"
  sourceFile Construction = "construction"
  sourceFile Cosmere = "cosmere"
  sourceFile CryptoCoin = "crypto_coin"
  sourceFile CultureSeries = "culture_series"
  sourceFile Currency = "currency"
  sourceFile DcComics = "dc_comics"
  sourceFile Demographic = "demographic"
  sourceFile Dessert = "dessert"
  sourceFile Device = "device"
  sourceFile Dog = "dog"
  sourceFile Dota = "dota"
  sourceFile DrWho = "dr_who"
  sourceFile DragonBall = "dragon_ball"
  sourceFile DumbAndDumber = "dumb_and_dumber"
  sourceFile Dune = "dune"
  sourceFile Educator = "educator"
  sourceFile ElderScrolls = "elder_scrolls"
  sourceFile ElectricalComponents = "electrical_components"
  sourceFile Esport = "esport"
  sourceFile Fallout = "fallout"
  sourceFile FamilyGuy = "family_guy"
  sourceFile File = "file"
  sourceFile Finance = "finance"
  sourceFile Food = "food"
  sourceFile Football = "football"
  sourceFile FreshPrinceOfBelAir = "fresh_prince_of_bel_air"
  sourceFile Friends = "friends"
  sourceFile FunnyName = "funny_name"
  sourceFile JackHandey = "jack_handey"
  sourceFile GameOfThrones = "game_of_thrones"
  sourceFile Gender = "gender"
  sourceFile GhostBusters = "ghostbusters"
  sourceFile GratefulDead = "grateful_dead"
  sourceFile GreekPhilosophers = "greek_philosophers"
  sourceFile Hacker = "hacker"
  sourceFile HalfLife = "half_life"
  sourceFile HarryPotter = "harry_potter"
  sourceFile Heroes = "heroes"
  sourceFile HeroesOfTheStorm = "heroes_of_the_storm"
  sourceFile HeyArnold = "hey_arnold"
  sourceFile Hipster = "hipster"
  sourceFile HitchhikersGuideToTheGalaxy = "hitchhikers_guide_to_the_galaxy"
  sourceFile Hobbit = "hobbit"
  sourceFile House = "house"
  sourceFile HowIMetYourMother = "how_i_met_your_mother"
  sourceFile IdNumber = "id_number"
  sourceFile IndustrySegments = "industry_segments"
  sourceFile Internet = "internet"
  sourceFile Invoice = "invoice"
  sourceFile Job = "job"
  sourceFile Kpop = "kpop"
  sourceFile LeagueOfLegends = "league_of_legends"
  sourceFile Lebowski = "lebowski"
  sourceFile LordOfTheRings = "lord_of_the_rings"
  sourceFile Lorem = "lorem"
  sourceFile LoveCraft = "lovecraft"
  sourceFile Markdown = "markdown"
  sourceFile Marketing = "marketing"
  sourceFile Measurement = "measurement"
  sourceFile MichaelScott = "michael_scott"
  sourceFile Military = "military"
  sourceFile Movie = "movie"
  sourceFile Music = "music"
  sourceFile Myst = "myst"
  sourceFile Nation = "nation"
  sourceFile NatoPhoneticAlphabet = "nato_phonetic_alphabet"
  sourceFile NewGirl = "new_girl"
  sourceFile OnePiece = "one_piece"
  sourceFile OverWatch = "overwatch"
  sourceFile ParksAndRec = "parks_and_rec"
  sourceFile Phish = "phish"
  sourceFile PhoneNumber = "phone_number"
  sourceFile Pokemon = "pokemon"
  sourceFile PrincessBride = "princess_bride"
  sourceFile ProgrammingLanguage = "programming_language"
  sourceFile Quote = "quote"
  sourceFile Relationship = "relationship"
  sourceFile Restaurant = "restaurant"
  sourceFile RickAndMorty = "rick_and_morty"
  sourceFile RockBand = "rock_band"
  sourceFile Rupaul = "rupaul"
  sourceFile Science = "science"
  sourceFile Seinfeld = "seinfeld"
  sourceFile Shakespeare = "shakespeare"
  sourceFile SiliconValley = "silicon_valley"
  sourceFile Simpsons = "simpsons"
  sourceFile SlackEmoji = "slack_emoji"
  sourceFile SonicTheHedgehog = "sonic_the_hedgehog"
  sourceFile Source = "source"
  sourceFile SouthPark = "south_park"
  sourceFile Space = "space"
  sourceFile StarTrek = "star_trek"
  sourceFile StarWars = "star_wars"
  sourceFile StarGate = "stargate"
  sourceFile StrangerThings = "stranger_thing"
  sourceFile Stripe = "stripe"
  sourceFile Subscription = "subscription"
  sourceFile SuperSmashBros = "super_smash_bros"
  sourceFile SuperHero = "superhero"
  sourceFile SwordArtOnline = "sword_art_online"
  sourceFile Team = "team"
  sourceFile TheExpanse = "the_expanse"
  sourceFile TheItCrowd = "the_it_crowd"
  sourceFile TheThickOfIt = "the_thick_of_it"
  sourceFile TwinPeaks = "twin_peaks"
  sourceFile UmphreysMcgee = "umphreys_mcgee"
  sourceFile University = "university"
  sourceFile VForVendetta = "v_for_vendetta"
  sourceFile Vehicle = "vehicle"
  sourceFile VentureBros = "venture_bros"
  sourceFile Verbs = "verbs"
  sourceFile Witcher = "witcher"
  sourceFile WorldCup = "world_cup"
  sourceFile WorldOfWarcraft = "world_of_warcraft"
  sourceFile Yoda = "yoda"
  sourceFile Zelda = "zelda"
  sourceFile Basketball = "basketball"
  sourceFile Opera = "opera"
  sourceFile Blood = "blood"
  sourceFile Chiquito = "chiquito"
  sourceFile Computer = "computer"
  sourceFile Control = "control"
  sourceFile Departed = "departed"
  sourceFile DnD = "dnd"
  sourceFile PearlJam = "pearl_jam"
  sourceFile Rajnikanth = "rajnikanth"
  sourceFile Show = "show"
  sourceFile WarhammerFantasy = "warhammer_fantasy"
  sourceFile Suits = "suits"
  sourceFile Barcode = "barcode"
  sourceFile DrivingLicense = "driving_license"
  sourceFile Drone = "drone"
  sourceFile Futurama = "futurama"
  sourceFile Minecraft = "minecraft"
  sourceFile Prince = "prince"
  sourceFile Rush = "rush"
  sourceFile StreetFighter = "street_fighter"
  sourceFile StudioGhibli = "studio_ghibli"
  sourceFile Bird = "bird"
  sourceFile Camera = "camera"
  sourceFile ClashOfClans = "clash_of_clan"
  sourceFile Conan = "conan"
  sourceFile Doraemon = "doraemon"
  sourceFile FinalSpace = "final_space"
  sourceFile HowToTrainYourDragon = "how_to_train_your_dragon"
  sourceFile Mountain = "mountain"
  sourceFile Naruto = "naruto"
  sourceFile Room = "room"
  sourceFile SuperMario = "super_mario"
  sourceFile Tea = "tea"
  sourceFile Tolkien = "tolkien"
  sourceFile Touhou = "touhou"
  sourceFile Volleyball = "volleyball"
  
  mapSource :: Text -> Name
  mapSource "studioGhibli" = 'StudioGhibli
  mapSource "streetFighter" = 'StreetFighter
  mapSource "prince" = 'Prince
  mapSource "minecraft" = 'Minecraft
  mapSource "futurama" = 'Futurama
  mapSource "rush" = 'Rush
  mapSource "drone" = 'Drone
  mapSource "drivingLicense" = 'DrivingLicense
  mapSource "barcode" = 'Barcode
  mapSource "pearl_jam" = 'PearlJam
  mapSource "dnd" = 'DnD
  mapSource "chiquito" = 'Chiquito
  mapSource "departed" = 'Departed
  mapSource "computer" = 'Computer
  mapSource "control" = 'Control
  mapSource "horse" = 'Horse
  mapSource "address" = 'Address
  mapSource "basketball" = 'Basketball
  mapSource "name" = 'Name
  mapSource "blood" = 'Blood
  mapSource "ancient" = 'Ancient
  mapSource "animal" = 'Animal
  mapSource "app" = 'App
  mapSource "appliance" = 'Appliance
  mapSource "aquaTeenHungerForce" = 'ATHF
  mapSource "artist" = 'Artist
  mapSource "backToTheFuture" = 'BTTF
  mapSource "bank" = 'Bank
  mapSource "beer" = 'Beer
  mapSource "bojackHourseman" = 'BoJackHorseman
  mapSource "book" = 'Book
  mapSource "bossaNova" = 'BossaNova
  mapSource "breakingBad" = 'BreakingBad
  mapSource "bigBangTheory" = 'BigBangTheory
  mapSource "buffy" = 'Buffy
  mapSource "business" = 'Business
  mapSource "cannabis" = 'Cannabis
  mapSource "cat" = 'Cat
  mapSource "chuckNorris" = 'ChuckNorris
  mapSource "code" = 'Code
  mapSource "coffee" = 'Coffee
  mapSource "coin" = 'Coin
  mapSource "color" = 'Color
  mapSource "commerce" = 'Commerce
  mapSource "community" = 'Community
  mapSource "company" = 'Company
  mapSource "construction" = 'Construction
  mapSource "cosmere" = 'Cosmere
  mapSource "cryptoCoin" = 'CryptoCoin
  mapSource "cultureSeries" = 'CultureSeries
  mapSource "currency" = 'Currency
  mapSource "dcComics" = 'DcComics
  mapSource "demographic" = 'Demographic
  mapSource "dessert" = 'Dessert
  mapSource "device" = 'Device
  mapSource "dog" = 'Dog
  mapSource "dota" = 'Dota
  mapSource "drWho" = 'DrWho
  mapSource "dragonBall" = 'DragonBall
  mapSource "dumbAndDumber" = 'DumbAndDumber
  mapSource "dune" = 'Dune
  mapSource "educator" = 'Educator
  mapSource "compass" = 'Compass
  mapSource "elderScrolls" = 'ElderScrolls
  mapSource "electricalComponents" = 'ElectricalComponents
  mapSource "esport" = 'Esport
  mapSource "fallout" = 'Fallout
  mapSource "familyGuy" = 'FamilyGuy
  mapSource "file" = 'File
  mapSource "finance" = 'Finance
  mapSource "food" = 'Food
  mapSource "football" = 'Football
  mapSource "freshPrinceOfBelAir" = 'FreshPrinceOfBelAir
  mapSource "friends" = 'Friends
  mapSource "funnyName" = 'FunnyName
  mapSource "gameOfThrones" = 'GameOfThrones
  mapSource "gender" = 'Gender
  mapSource "ghostbusters" = 'GhostBusters
  mapSource "gratefulDead" = 'GratefulDead
  mapSource "greekPhilosophers" = 'GreekPhilosophers
  mapSource "hacker" = 'Hacker
  mapSource "halfLife" = 'HalfLife
  mapSource "harryPotter" = 'HarryPotter
  mapSource "heroes" = 'Heroes
  mapSource "heroesOfTheStorm" = 'HeroesOfTheStorm
  mapSource "heyArnold" = 'HeyArnold
  mapSource "hipster" = 'Hipster
  mapSource "hitchhikersGuideToTheGalaxy" = 'HitchhikersGuideToTheGalaxy
  mapSource "hobbit" = 'Hobbit
  mapSource "house" = 'House
  mapSource "howIMetYourMother" = 'HowIMetYourMother
  mapSource "idNumber" = 'IdNumber
  mapSource "industrySegments" = 'IndustrySegments
  mapSource "internet" = 'Internet
  mapSource "invoice" = 'Invoice
  mapSource "job" = 'Job
  mapSource "kpop" = 'Kpop
  mapSource "leagueOfLegends" = 'LeagueOfLegends
  mapSource "lebowski" = 'Lebowski
  mapSource "lordOfTheRings" = 'LordOfTheRings
  mapSource "lorem" = 'Lorem
  mapSource "lovecraft" = 'LoveCraft
  mapSource "markdown" = 'Markdown
  mapSource "marketing" = 'Marketing
  mapSource "michaelScott" = 'MichaelScott
  mapSource "military" = 'Military
  mapSource "movie" = 'Movie
  mapSource "music" = 'Music
  mapSource "myst" = 'Myst
  mapSource "nation" = 'Nation
  mapSource "natoPhoneticAlphabet" = 'NatoPhoneticAlphabet
  mapSource "newGirl" = 'NewGirl
  mapSource "onePiece" = 'OnePiece
  mapSource "overwatch" = 'OverWatch
  mapSource "parksAndRec" = 'ParksAndRec
  mapSource "phish" = 'Phish
  mapSource "phoneNumber" = 'PhoneNumber
  mapSource "pokemon" = 'Pokemon
  mapSource "princessBride" = 'PrincessBride
  mapSource "programmingLauguage" = 'ProgrammingLanguage
  mapSource "quote" = 'Quote
  mapSource "relationship" = 'Relationship
  mapSource "restaurant" = 'Restaurant
  mapSource "rickAndMorty" = 'RickAndMorty
  mapSource "rockBand" = 'RockBand
  mapSource "rupaul" = 'Rupaul
  mapSource "science" = 'Science
  mapSource "seinfeld" = 'Seinfeld
  mapSource "shakespeare" = 'Shakespeare
  mapSource "siliconValley" = 'SiliconValley
  mapSource "simpsons" = 'Simpsons
  mapSource "slackEmoji" = 'SlackEmoji
  mapSource "sonicTheHedgehog" = 'SonicTheHedgehog
  mapSource "source" = 'Source
  mapSource "southPark" = 'SouthPark
  mapSource "space" = 'Space
  mapSource "starTrek" = 'StarTrek
  mapSource "starWars" = 'StarWars
  mapSource "stargate" = 'StarGate
  mapSource "strangerThings" = 'StrangerThings
  mapSource "stripe" = 'Stripe
  mapSource "subscription" = 'Subscription
  mapSource "superSmashBros" = 'SuperSmashBros
  mapSource "superhero" = 'SuperHero
  mapSource "swordArtOnline" = 'SwordArtOnline
  mapSource "team" = 'Team
  mapSource "theExpanse" = 'TheExpanse
  mapSource "theItCrowd" = 'TheItCrowd
  mapSource "theThickOfIt" = 'TheThickOfIt
  mapSource "twinPeaks" = 'TwinPeaks
  mapSource "umphreysMcgee" = 'UmphreysMcgee
  mapSource "university" = 'University
  mapSource "vForVendetta" = 'VForVendetta
  mapSource "vehicle" = 'Vehicle
  mapSource "ventureBros" = 'VentureBros
  mapSource "verbs" = 'Verbs
  mapSource "witcher" = 'Witcher
  mapSource "worldCup" = 'WorldCup
  mapSource "worldOfWarcraft" = 'WorldOfWarcraft
  mapSource "yoda" = 'Yoda
  mapSource "zelda" = 'Zelda
  mapSource "measurement" = 'Measurement
  mapSource "opera" = 'Opera
  mapSource "rajnikanth" = 'Rajnikanth
  mapSource "show" = 'Show
  mapSource "suits" = 'Suits
  mapSource "warhammerFantasy" = 'WarhammerFantasy
  mapSource "adjective" = 'Adjective
  mapSource "bird" = 'Bird
  mapSource "camera" = 'Camera
  mapSource "clashOfClans" = 'ClashOfClans
  mapSource "conan" = 'Conan
  mapSource "doraemon" = 'Doraemon
  mapSource "finalSpace" = 'FinalSpace
  mapSource "howToTrainYourDragon" = 'HowToTrainYourDragon
  mapSource "jackHandey" = 'JackHandey
  mapSource "mountain" = 'Mountain
  mapSource "naruto" = 'Naruto
  mapSource "room" = 'Room
  mapSource "superMario" = 'SuperMario
  mapSource "tea" = 'Tea
  mapSource "tolkien" = 'Tolkien
  mapSource "touhou" = 'Touhou
  mapSource "volleyball" = 'Volleyball
  mapSource item = error $ "mapSource: Invalid argument passed " <> (show item)
  
  guessSourceFile :: SourceData -> Text -> FilePath
  guessSourceFile sdata sysloc =
    case sysloc of
      "en" ->
        case sdata of
          Finance -> localesCustomEnDirectory </> (sourceFile sdata) <.> "yml"
          sdata' -> localesEnDirectory </> (sourceFile sdata') <.> "yml"
      "ja" -> localesDirectory </> "ja" </> (sourceFile sdata) <> ".yml"
      "fr" -> localesDirectory </> "fr" </> (sourceFile sdata) <> ".yml"
      oth -> localesDirectory </> (unpack oth <> ".yml")
  
  getSourceFile :: (MonadThrow m, MonadIO m) => FilePath -> m FilePath
  getSourceFile fname = do
    fname' <- liftIO $ getDataFileName fname
    exist <- liftIO $ doesFileExist fname'
    if exist
      then pure fname'
      else throwM $ InvalidLocale fname'
  
  fetchData ::
       (MonadThrow m, MonadIO m)
    => FakerSettings
    -> SourceData
    -> (FakerSettings -> Value -> Parser a)
    -> m a
  fetchData settings sdata parser = do
    let locale = getLocale settings
        fname = guessSourceFile sdata locale
        ckey = CacheFileKey {cfkSource = sdata, cfkLocale = locale}
    cache <- liftIO $ getCacheFile settings
    case (HM.lookup ckey cache) of
      Nothing -> do
        afile <- getSourceFile fname
        bs <- liftIO $ BS.readFile afile
        yaml <- decodeThrow bs
        let nhash = HM.insert ckey yaml cache
        liftIO $ setCacheFile nhash settings
        either (throwM . ParseError) pure (parseEither (parser settings) yaml)
      Just yaml ->
        either (throwM . ParseError) pure (parseEither (parser settings) yaml)
  
  fetchDataSingle ::
       (MonadThrow m, MonadIO m)
    => FakerSettings
    -> SourceData
    -> (FakerSettings -> Value -> Parser Text)
    -> m (Vector Text)
  fetchDataSingle settings sdata parser = do
    let locale = getLocale settings
        fname = guessSourceFile sdata locale
        ckey = CacheFileKey {cfkSource = sdata, cfkLocale = locale}
    cache <- liftIO $ getCacheFile settings
    case (HM.lookup ckey cache) of
      Nothing -> do
        afile <- getSourceFile fname
        bs <- liftIO $ BS.readFile afile
        yaml <- decodeThrow bs
        let nhash = HM.insert ckey yaml cache
        liftIO $ setCacheFile nhash settings
        pure <$>
          either (throwM . ParseError) pure (parseEither (parser settings) yaml)
      Just yaml ->
        pure <$>
        either (throwM . ParseError) pure (parseEither (parser settings) yaml)
  