(local { : Gtk : Gdk : WebKit2 : cairo } (require :lgi))
(local { : view } (require :fennel))

(fn new-buffer [name]
  (var property-change-listener nil)
  (let [props {}
        widget (WebKit2.WebView {
                                 ;; :on_decide_policy
                                 ;; (fn [self decision dtype]
                                 ;;   (if (and
                                 ;;        (WebKit2.ResponsePolicyDecision:is_type_of decision)
                                 ;;        (not (decision:is_mime_type_supported)))
                                 ;;       (do
                                 ;;         (download decision.request.uri decision.response.http_headers)
                                 ;;         (decision:ignore)
                                 ;;         true)
                                 ;;       false))
                                 :on_notify
                                 (fn [self pspec]
                                    (when (not (= pspec.name :parent))
                                      (let [val (. self pspec.name)]
                                        (tset props pspec.name val)
                                        (when property-change-listener
                                          (property-change-listener
                                           pspec.name val)))
                                        ))
                                 })]
    {:webview widget
     :name name
     :subscribe-property-changes
     (fn [self cb]
       (set property-change-listener cb))
     :location #(widget:get_uri)
     :visit (fn [_ u] (widget:load_uri u))
     :properties props}))

(let [buffers {}]
  {
   :new (fn [name]
          (let [b (new-buffer name)]
            (tset buffers name b)
            b))
   :find (fn [term] (. buffers term))
   ;; will rename this to "find" once we've got rid of the
   ;; only remaining call to the existing Buffer.find
   :match (fn [s] (collect [name buffer (pairs buffers)]
                    (if (string.find name s)
                        (values name buffer))))
   :next (fn [buffer]
           (let [n (or (next buffers buffer.name) (next buffers))]
             (. buffers n)))

   })