{-# LANGUAGE OverloadedStrings, TemplateHaskell, FlexibleContexts
  #-}

-- | Dump all contracts.
module Ethereum.Executable.DumpCodeMain
  ( dumpContracts
  ) where

import Prelude

import Control.Monad.Logger
import Control.Monad.Trans
import Data.Maybe
import Data.Text as T hiding (map)
import Ethereum.Jsonrpc.Client
import Numeric
import System.Directory as SD

dumpContracts :: String -> Int -> String -> LoggingT IO ()
dumpContracts server port contractDir = do
  $logInfo "Dumping eth contracts."
  ver <- web3ClientVersion server port
  $logInfo $ T.append "version is " ver
  latest_bNum <- ethBlockNumber server port
  let parsed_bns = readHex $ Prelude.drop 2 $ T.unpack latest_bNum
  $logInfo $ T.pack $ "parsing block number: " ++ show parsed_bns
  let latest_bn = fst $ Prelude.head parsed_bns
  $logInfo $ T.pack $ "block number is " ++ show latest_bn
  enumerateContractAt server port contractDir latest_bn
  return ()

enumerateContractAt :: String -> Int -> String -> Int -> LoggingT IO ()
enumerateContractAt _ _ _ 0 = return ()
enumerateContractAt s p contractDir bn = do
  $logInfo $ T.pack $ "processing block " ++ show bn
  transactions <- ethGetTransactionsByBlockNumber s p (T.pack $ show bn)
  addresses <- catMaybes <$> mapM (ethGetContractAddrByTxHash s p) transactions
  mapM_
    (\addr -> do
       let fpath = contractDir ++ "/" ++ T.unpack addr ++ ".contract"
       fileExists <- lift $ doesFileExist fpath
       if fileExists
         then $logInfo $ T.pack $ "skipping: " ++ show addr
         else do
           textCode <- ethGetCode s p addr
           lift $ writeFile fpath $ T.unpack $ T.drop 2 textCode)
    addresses
  enumerateContractAt s p contractDir (bn - 1)