 ; Copyright (C) 2013, 2014, 2015 Dr. Thomas Schank  (DrTom@schank.ch, Thomas.Schank@algocon.ch)
 ; Licensed under the terms of the GNU Affero General Public License v3.
 ; See the "LICENSE.txt" file provided with this software.
-
 (ns cider-ci.ex.scripts.exec
   (:import 
     [org.apache.commons.exec ExecuteWatchdog]
     [java.io File]
     )
-
   (:require 
     [cider-ci.utils.config :as config :refer [get-config]]
-    [clojure.string :as string]
     [clj-commons-exec :as commons-exec]
     [clj-logging-config.log4j :as logging-config]
+    [clj-time.core :as time]
+    [clojure.set :refer [difference union]]
+    [clojure.string :as string :refer [split trim]]
+    [clojure.tools.logging :as logging]
     [drtom.logbug.debug :as debug]
-    [clojure.tools.logging :as logging]
-    [clj-time.core :as time]
     [drtom.logbug.thrown :as thrown]
-
     ))
 
 ; TODO us clj-fs or our fs ..

(defn- interpreter [env_vars]
  (flatten ["sudo" "-u" (get-exec-user) env_vars  "-n" "-i"]))

(defn- create-command-wrapper-file [working-dir script-file]
  (let [command-wrapper-file (File/createTempFile "cider-ci_", ".command_wrapper")
        script (str "cd '" working-dir "' && " (.getAbsolutePath script-file)) ]
    (.deleteOnExit command-wrapper-file)
    (spit command-wrapper-file script)
    (.setExecutable command-wrapper-file true false)
    (.getAbsolutePath command-wrapper-file)))


(defn- command [script-file working-dir env-variables]
  (flatten (concat (interpreter (sudo-env env-variables)) 
                   [(create-command-wrapper-file working-dir script-file)])))


(defn- commons-exec-sh [command env-variables watchdog]
  (commons-exec/sh 
    command 
    {:env (conj {} (System/getenv) env-variables)
     :watchdog watchdog}))


(defn exec-future [params timeout-or-watchdog]
  (let [env-variables (prepare-env-variables params)
        script-file (prepare-script-file (:body params))  
        command (command script-file (working-dir params) env-variables)]
    (logging/debug {:command command})
    (commons-exec-sh command env-variables timeout-or-watchdog)))


(defn- get-final-parameters [exec-res]
  {:finished_at (time/now)

  (debug-recent-execs-push script-atom)
  (try (let [params @script-atom
             timeout (or (:timeout params) 200)
             started-at (time/now)
             watchdog (create-watchdog timeout)]
         (logging/debug "TIMEOUT" timeout)
         (swap! script-atom 
                (fn [params watchdog started-at]
                  (conj params
                        {:started_at started-at
                         :state "executing"}
                        (when watchdog
                          {:watchdog watchdog})))
                watchdog started-at)
         (let [exec-future (exec-sh params watchdog)]
           (loop []
             (when (time/after? (time/now) 
                                (time/plus started-at (time/seconds timeout)))
               (terminate exec-future script-atom))
             (when-not (realized? exec-future)
               (Thread/sleep 500)
               (recur)))
           (swap! script-atom
                  (fn [params res]
                    (conj params res))
                  (get-final-parameters @exec-future))))
       (catch Exception e
         (set-script-atom-for-execption script-atom e))))

