 (ns edu.berkeley.ai.search.smart-csps
  (:refer-clojure)
- (:import [java.util HashMap])
+ (:import [java.util HashMap Map ArrayList])
  (:require [edu.berkeley.ai.util :as util] 
 	   [edu.berkeley.ai.util.propositions :as props]
 	   )

	                const-domain
	              pos-fluent)
	          neg-fluent)])
	     clause-maps)]
;      (println clause-domains "\n\n\n\n")
      (util/forcat [val (apply util/union (map second clause-domains))]
	(all-solutions 
	 (rest vars-left)
	 initial-domains
	 var-map
	 (simplify-map const-map (concat pos-const neg-const) val)
	 (map #(simplify-map % (concat pos-fluent neg-fluent) val) (map first (filter #((second %) val) clause-domains)))
	 (if arg? inst-map (assoc inst-map var val)))))))



(defstruct smart-csp :ordered-vars :unk-domains :var-pred-map :const-map :fluent-map-maker :unary-var :unary-val)

(defn get-smart-csp-solutions [csp var-values allowed-pred-inst-maps]
  (all-solutions 
   (util/safe-get csp :ordered-vars)
   (assoc


; Returns new-domain
; TODO: change to use keyset
(defn filter-pos-domain [#^HashMap map pred domain]
;  (println "fpd" map pred domain)
  (util/intersection-coll domain (if-let [#^Map m (first (.get map pred))] (.keySet m) nil)))

;; TODO: make smarter?
(defn filter-neg-domain [map pred domain]
;  (println map pred domain)
  (let [sub (first (get map pred))]
    (reduce (fn [domain val] (if (true? (get sub val)) (disj domain val) domain)) domain domain)))
;  (util/difference domain (util/keyset (get map pred {}))))

;(defn simplify-map [#^HashMap map preds val]
;  (if (empty? preds) map
;    (let [#^HashMap m (.clone map)]
;      (doseq [pred preds]
;        (.put m pred (get (.get m pred) val)))
;      m))) 

(defn simplify-map [#^HashMap map preds val]
;  (println "simpl" map preds val)
  (doseq [pred preds]
    (let [sub (.get map pred)
	  fs (first sub)]
      (.put map pred (cons (get fs val) sub)))))


(defn unsimplify-map [#^HashMap map preds val]
  (doseq [pred preds]
    (.put map pred (rest (.get map pred)))))
;  (reduce (fn [map pred] (assoc map pred (get (get map pred) val)))
;	  map preds))


(defn- all-solutions [vars-left initial-domains var-map const-map clause-maps inst-map #^ArrayList results]
;  (println vars-left initial-domains var-map const-map clause-maps inst-map "\n\n")
  (if (empty? vars-left) (.add results inst-map);[inst-map]
    (let [[var arg?]    (first vars-left)
	  [pos-const neg-const pos-fluent neg-fluent] (util/safe-get var-map var)
	  const-domain 
