(ns hooks.defstate
  (:require [clj-kondo.hooks-api :as api]))

(defn defstate [{:keys [:node]}]
  (let [args (rest (:children node))
        args (if (string? (api/sexpr (first args)))
               (next args)
               args)
        [n & args] args
        m (when-let [m (first (:meta n))]
            (api/sexpr m))
        m (if (map? m) m {})
        ks (cond-> (take 1 args)
                   (> (count args) 2) (conj (nth args 2)))
        invalid-key (first (remove (comp (partial contains? #{:start :stop}) api/sexpr) ks))]
    (cond
      invalid-key
      (api/reg-finding!
        {:message (str "lifecycle functions can only contain `:start` and `:stop`. illegal function found: " (api/sexpr invalid-key))
         :type    :mount/defstate
         :row     (:row (meta invalid-key))
         :col     (:col (meta invalid-key))})
      (not (contains? (set (map api/sexpr ks)) :start))
      (throw (ex-info "lifecycle functions must include `:start`" {}))
      ((complement contains?) #{2 4} (count args))
      (throw (ex-info "lifecycle functions must consist of no more than 2 pair forms: `:start` and `:stop`" {}))
      (and (contains? m :on-reload) (not (contains? #{:noop :stop} (:on-reload m))))
      (api/reg-finding!
        {:message "metadata `:on-reload` key can only have value of `noop` or `stop`"
         :type    :mount/defstate
         :row     (:row (meta n))
         :col     (:col (meta n))})
      :else
      {:node
       (api/list-node
         (list
           (api/token-node 'def)
           n
           (api/list-node 
             (list* 
               (api/token-node 'do)
               (list* 
                 
                 (api/token-node 'fn)
                 (api/vector-node [])
                 args)))))})))
