;;
;; Copyright 1337 (c) by Kirill Miazine
;;

;;; sla
(define (get-path-sla)
  (float (replace "," (slice (or (env "PATH_INFO") "/") 1) ".")))

(define (get-form-sla)
  (float (replace "," (or (Web:post "sla") (Web:get "sla") "") ".")))

(define (get-sla)
  (let
    (sla (or (get-form-sla) (get-path-sla) 99.9))
    (cond
      ((< sla 0.0) 0.0)
      ((> sla 100.0) 100.0)
      (true sla))))

(define (fmt-sla sla)
  (if (= sla 0)
    (string sla)
    (trim (trim (format "%.9f" sla) "0") ".")))

(define (fmt-down down)
  (if (< down 0) "0" (trim (trim (format "%.3f" down) "0") ".")))

;;; durations
(setq seconds-day (mul 3600 24))
(setq hours-day 24)
(setq days-week 7)
(setq months-year 12)
(setq days-year 365.2425) ; pick one at http://en.wikipedia.org/wiki/Year#Summary
(setq weeks-year (div days-year days-week))
(setq days-month (div days-year months-year))
(setq weeks-month (div days-month days-week))
(setq hours-month (mul hours-day days-month))
(setq hours-year (mul hours-day days-year))
(setq hours-week (mul hours-day days-week))

;;; for complex and reverse calculations
(setq days-en '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"))

;;; for encoding uptime durations
(setq letters (explode "abcdefghijklmnopqrstuvwxyz"))
(setq srettel (map (fn (l) (list l $idx)) (explode "abcdefghijklmnopqrstuvwxyz")))

(define (fix-dur dur)
  (cond
    ((not (float dur)) 24)
    ((< (float dur) 0) 0)
    ((> (float dur) 24) 24)
    (true (float dur))))

(define (get-dur)
  (let
    (wk (lower-case (trim (or (Web:post "wk") (Web:get "wk") ""))))
    (if (regex {^[a-z]{1,7}+$} wk)
      (map (fn (x) (lookup x srettel)) (explode wk))
      (map (fn (x) (x 1))
           (filter
             (fn (x) (= "dur" (x 0)))
             (or (Web:post) (Web:get) '()))))))

(define (zip) (transpose (args)))
(define (get-days-dur)
  (map (fn (x) (list (x 0) (fix-dur (x 1))))
       (zip days-en (0 (length days-en) (get-dur)))))

(define (get-down-dur)
  (lower-case (trim (or (Web:post "down") (Web:get "down") "1337s"))))

(setq dur-hours-week (apply add (map (fn (x) (x 1)) (get-days-dur))))
(setq dur-seconds-week (mul dur-hours-week 3600))
(setq dur-seconds-day (div dur-seconds-week days-week))
(setq dur-seconds-month (mul dur-seconds-week weeks-month))
(setq dur-seconds-quarter (mul dur-seconds-month 3))
(setq dur-seconds-year (mul dur-seconds-week weeks-year))

;;; quick and ugly multilanguage format monster
(define (fmt-secs sec lang skip-days)
  (let
    (htag (if (= lang "no") "t" "h")) ; lang is not used anymore, but anyway
    (cond
      ((< sec 60)
       (format "%ds" (float sec)))
      ((< sec 3600)
       (letn
         (mins (/ sec 60)
          secs (sub sec (* mins 60)))
         (format "%dm %ds" mins (float secs))))
      ((or (< sec 86400) skip-days)
       (letn
         (hours (/ sec 3600)
          mins (/ (sub sec (* hours 3600)) 60)
          secs (sub sec (* hours 3600) (* mins 60)))
         (format "%d%s %dm %ds" hours htag mins (float secs))))
      (true
        (letn
          (days (/ sec 86400)
           hours (/ (sub sec (* days 86400)) 3600)
           mins (/ (sub sec (* days 86400) (* hours 3600)) 60)
           secs (sub sec (* days 86400) (* hours 3600) (* mins 60)))
          (format "%dd %d%s %dm %ds" days hours htag mins (float secs)))))))

;;; quick and beautiful unformat ... monster
(define (dur2secs dur)
  (if (regex {^\d+$} dur)
    (integer dur)
    (apply add (map (fn (x)
                        (mul
                          (integer (0 -1 x))
                          (case (x -1)
                            ("d" 86400)
                            ("h" 3600)
                            ("t" 3600)
                            ("m" 60)
                            ("s" 1)
                            (true 1))))
                    (find-all {\d+[dhtms]} dur)))))

;;; N nines
(define (get-nines sla)
  (letn
    (s (fmt-sla sla)
     l (- (length s) 1) ; we don't want fewer than 2 nines anyway
     a (= l (length (find-all "9" s))))
    (if (and
          (> sla 99)
          a
          (< l 10))
      ('("zero" "one" "two" "three" "four"
         "five" "six" "seven" "eight" "nine") l)
      nil)))

(define (fmt-nines sla)
  (let
    (nines (get-nines sla))
    (if nines (format "%s nines" nines) "")))

;;; helpers
(Web:header "Content-type"
            (string 
              (if
                (or (or (Web:post "node") (Web:get "node"))
                    (or (Web:post "clean") (Web:get "clean"))) "text/plain"
                (or (Web:post "json") (Web:get "json")) "application/json"
                "text/html")
              "; charset=utf-8"))

(define (die msg) (Web:send-headers) (println msg) (exit))
; vim: set tw=76 ts=2 fileencoding=utf8 ft=lisp et: