(create-probe
 check-file-exists
 (let ((result (probe-file (getf params :path))))
   (if result
       t
       (list nil "file not found"))))

(create-probe
 file-updated
 (if (probe-file (getf params :path))
     (with-open-file (file (getf params :path))
       (let* ((write-date (file-write-date file))
	      (now (get-universal-time))
	      (result (floor (- now write-date) 60)))
	 (if (> (getf params :limit) result)
	     t
	     (list nil result))))
     (list nil "file not found")))

(create-probe
 service
 (command-return-code
  #+openbsd
  (list "/usr/sbin/rcctl" "check" (getf params :name))
  #+freebsd
  (list "/usr/sbin/service" (getf params :name) "status")
  #+linux
  (if (probe-file "/etc/portage/make.conf")
      ;; gentoo
      (list "/sbin/rc-service" (getf params :name) "status")
      ;; most linux
      (if (probe-file "/usr/sbin/service")
         (list "/usr/sbin/service" (getf params :name) "status")
         ;; other linux with systemd only
         (list "/usr/bin/systemctl" "status" (getf params :name))))))

(create-probe
 pid-running
 (if (probe-file (getf params :path))
     (let ((pid-number (with-open-file (stream (getf params :path)) (read-line stream))))
       (command-return-code (list "ps" "-p" pid-number)))
     (list nil "file not found")))

(create-probe
 disk-usage
 (let* ((output (uiop:run-program (list "df" (getf params :path)) :output :lines)) (line (second output)))
   (let ((percent-character-pos (position #\% line)))
     (let ((used-disk
	    (parse-integer
	     (subseq line
		     (position #\Space line :end percent-character-pos :from-end t)
		     percent-character-pos))))
       (if (< used-disk (getf params :limit))
	   t
	   (list nil used-disk))))))

(defun system-load(time)
  (read-from-string
   (let ((command (strcat
		   "uptime | awk '{ print $(NF-"
		   (princ-to-string time)
		   ") }'")))
     (uiop:run-program command :output :string))))
    
(create-probe
 load-average-1
 (let ((load (system-load 2)))
   (if (< load (getf params :limit))
       t
       (list nil load))))

(create-probe
 load-average-5
 (let ((load (system-load 1)))
   (if (< load (getf params :limit))
       t
       (list nil load))))
 
(create-probe
 load-average-15
 (let ((load (system-load 0)))
   (if (< load (getf params :limit))
       t
       (list nil load))))

(create-probe
 file-more-than
 (if (probe-file (getf params :path))
     (let ((result (get-file-size (getf params :path))))
       (if (< result (getf params :limit))
	   t
	   (list nil result)))
     "file not found"))

(create-probe
 file-less-than
 (if (probe-file (getf params :path))
     (let ((result (get-file-size (getf params :path))))
       (if (> result (getf params :limit))
	   t
	   (list nil result)))
     "file not found"))

(create-probe
 command
 (command-return-code (getf params :command)))

(create-probe
 ping
 (command-return-code
   #+openbsd
   (list "ping" "-w1" "-c2" (getf params :host))
   #+freebsd
   (list "ping" "-W1" "-c2" (getf params :host))
   #+linux
   (list "ping" "-W1" "-c2" (getf params :host))))

(create-probe
 number-of-processes
 (let* ((output (uiop:run-program (list "ps" "aux") :output :lines))
	(result (length output)))
   (if (> (getf params :limit) result)
       t
       (list nil result))))

(create-probe
 curl-http-status
 (command-return-code
  (list "curl" "-f"
        (format nil "-m~a" (getf params :timeout 5))
        (getf params :url))))

(create-probe
 ssl-expiration
 (command-return-code
  (let ((host (getf params :host))
        (port (princ-to-string (getf params :port 443)))
        (seconds (princ-to-string (getf params :seconds)))
        (starttls (getf params :starttls)))
    (strcat
     "echo | openssl s_client -showcerts -servername " host
     " -connect "  host ":" port " 2>/dev/null |"
     "openssl x509 -inform pem -noout "
     (when starttls (strcat " -starttls " starttls))
     " -checkend " seconds))))

(create-probe
 write-to-file
 (let ((filepath (getf params :path nil))
       (text (getf params :text
                   (princ-to-string
                    (get-universal-time)))))
   (when filepath
     (with-open-file
         (stream-out filepath
                     :direction :output
                     :if-exists :supersede)
       (format stream-out "~a~%" text))
     t)))
