import System.Environment
import Network.HTTP
import Text.Printf
import Text.Regex.TDFA
import Data.List
import Data.Array
import qualified Data.Map as Map


splitByMatches :: String -> [MatchText String] -> [String]
splitByMatches str matches  =  foldr splitHead [str] matches
    where splitHead match acc  =  before:after:(tail acc)
            where before  =  take (matchOffset).head$ acc
                  after  =  drop (matchOffset + matchLen).head$ acc
                  matchOffset  =  fst.snd.(!0)$ match
                  matchLen  =  snd.snd.(!0)$ match


countBareLangTags :: String -> Int
countBareLangTags  =  matchCount (makeRegex "<lang[[:space:]]*>" :: Regex)


countByLanguage :: String -> Map.Map String Int
countByLanguage str  =  Map.fromList.filter ((>0).snd)$ zip langs counts
    where counts  =  map countBareLangTags.splitByMatches str$ allMatches
          langs  =  "":(map (fst.(!1)) allMatches)
          allMatches  =  matchAllText (makeRegex headerRegex :: Regex) str
          headerRegex  =  "==[[:space:]]*{{[[:space:]]*header[[:space:]]*\\|[[:space:]]*([^ }]*)[[:space:]]*}}[^=]*=="

main = do
    args <- getArgs
    (contents, files) <- if length args == 0 then do
        
            content  <-  getContents
            return ([content],[""])
        else if length args == 1 then do
        
        
            content  <-  readFile (head args)
            return ([content],[""])
        else if (args !! 0) == "-w" then do
        
        
            contents  <-  mapM getPageContent.tail$ args
            return (contents, if length args > 2 then tail args else [""])
        else do
        
            contents  <-  mapM readFile args
            return (contents, args)
    let tagsPerLang  =  map countByLanguage contents
    let tagsWithFiles  =  zipWith addFileToTags files tagsPerLang
    let combinedFiles  =  Map.unionsWith combine tagsWithFiles
    printBareTags combinedFiles
        where addFileToTags file  =  Map.map (flip (,) [file])
              combine cur next  =  (fst cur + fst next, snd cur ++ snd next)

printBareTags :: Map.Map String (Int,[String]) -> IO ()
printBareTags tags  =  do
    let numBare  =  Map.foldr ((+).fst) 0 tags
    printf "%d bare language tags:\n\n" numBare
    mapM_ (\(lang,(count,files)) ->
        printf "%d in%s%s\n" count
                              (if lang == "" then "no language" else lang)
                              (filesString files)
        ) (Map.toAscList tags)

filesString :: [String] -> String
filesString []  =  ""
filesString ("":rest)  =  filesString rest
filesString files  =  " ("++listString files++")"
    where listString [file]  =  "[["++file++"]]"
          listString (file:files)  =  "[["++file++"]], "++listString files

getPageContent :: String -> IO String
getPageContent title  =  do
    response  <-  simpleHTTP.getRequest$ url
    getResponseBody response
        where url  =  "http://rosettacode.org/mw/index.php?action=raw&title="++title