; ---- Eliminate the tiny, unwanted connections with a cutoff in the
;         (cell_area, worst_bounding_path_score) plane ----

;      if outside cutoff, remove the worst_bounding_path

; ---- Segmentation & Unique Path Labeling ----
(ns Path_Finder.tinycell
  [:use Path_Finder.drawing]
  [:use     [clojure.pprint :only [print-table pprint]]]
  [:import BinaryLabel_])

  ; (use '[Path_Finder.main_ :only [params]])
  ; (use '[Path_Finder.pathfinder :only [path_img paths scores]])


; (def path_img  (make-16bit-img "Paths" "blue orange icb" (.getWidth mem) (.getHeight mem)))
; (def paths )
; (def good_path_ids (range 0 ))

(defn remove-tiny-cells [vertex_img
						 path_img
                         good_path_ids
                         paths
                         scores
                         f_minarea
						 cutoff]

  ; (def path_img_b  (make-16bit-img "Paths" "blue orange icb" (.getWidth path_img) (.getHeight path_img)))
  ; (def path_proc_b (.convertToByte (.getProcessor path_img) true))
  ; (.threshold path_proc_b 0)
  ; (.setProcessor path_img_b path_proc_b)

  ; (exec [ImagePlus Name white-particles? 4-connected?])
  ; (let [result (.exec (BinaryLabel_.) path_img_b "Labelled" false true)]
  ;   (def result_img (aget result 1)))
  (def result_img (get-cell-img path_img))

  ; convert default 32-bit imgs. 16-bit is still big enough to uniquely label paths
  (def result_proc (.. result_img getProcessor (convertToShort false)))
  (.setProcessor result_img result_proc)
  (.show result_img)

  (def bigvalue 2000)
  ; add paths to img mapped by unique-id
  (let [paths   (map #(paths %)  good_path_ids)
        big_ids (map #(+ bigvalue %) good_path_ids)] ; add bigvalue so we don't confuse paths with cells!
    (redraw-paths (map list paths big_ids) result_proc))
  ; (.close path_img_b)

  (ij.IJ/log "Creating Mapping…")
  
  (def vertex_proc (.getProcessor vertex_img))

  ; ---- Create Cell → [Paths] mapping ----
  (def mapping (atom {}))
  (doseq [i (range 1 (dec (.getWidth path_img)))
          j (range 1 (dec (.getHeight path_img)))
          :let [mykey (.get result_proc i j)]
          :when (< 1 mykey bigvalue)] ; ignore background labelled 1
    (let [
        ; values of 4-connected neibs
        isNoVertex (map #(if (< 0 (.get vertex_proc (+ i %1) (+ j %2))) 0 1) [1 -1 0 0] [0 0 1 -1])
		arg1 (map #(* %1 %2) isNoVertex [1 -1 0 0])
		arg2 (map #(* %1 %2) isNoVertex [0 0 1 -1])
        nvals (map #(.get result_proc (+ i %1) (+ j %2)) arg1 arg2)
;        nvals (map #(.get result_proc (+ i %1) (+ j %2)) [1 -1 0 0] [0 0 1 -1])
        ; keep the ones that are path-ids
        gdns  (filter #(> % bigvalue) nvals)
        ; get set of values mapped-to by key
        ;   if it's new, then return the empty set
        ;   then add all the new path values to the set
        s (into (@mapping mykey #{}) gdns)]
      ; update mapping with the new set!
      (swap! mapping #(assoc % mykey s))))

  ; (println "The mapping is: ")
  ; (pprint mapping)

  (ij.IJ/log "Done with Mapping")

  ; Now use `mapping` to eliminate the small cells
  (def histo (.getHistogram result_proc))
  (def cell_ids (range 1 (inc (count @mapping))))
  (def cell_area (map #(aget histo %) cell_ids))
  ; now all cells need to go through the testing...
  ; (def small_cells (filter #(> 64 (first %)) (map list cell_area cell_ids)))
  (def small_cells (filter #(> 64000 (first %)) (map list cell_area cell_ids)))
  (def path_sets (map (fn [[ca cid]] [(@mapping cid) ca cid]) small_cells))

  ; (println "The small cells are: ")
  ; (pprint small_cells)

  ; (println "The path sets are: ")
  ; (pprint path_sets)

  (let [f1 (fn [elem] (- elem bigvalue)) ; convert back to normal path_id
        f2 (fn [elem] [elem (scores elem)]) ; pair each bounding path with it's score
        f3 (fn [set]  (map (comp f2 f1) set)) ; do above for each path bounding cell
        f4 (fn [lst]  (sort-by second lst))] ; sort resulting paths by score
    ; get the highest scoring path_id for each cell in a [[path_id score] cell_area cell_id] tuple
    (def paths_to_remove (map (fn [[ps ca cid]] [((comp last f4 f3) ps) ca]) path_sets)))
  ;  (def paths_to_remove (map (fn [[ps ca cid]] [((comp f4 f3) ps) ca cid]) path_sets)))

  ; (println "The highest scoring paths are: ")
  ; (pprint paths_to_remove)

  ; (def f_minarea (Path_Finder.main_/params :minarea))
  (def paths_to_remove_2 (filter (fn [[[pid scr] ca]] (or (< (f_minarea ca) scr) (> scr cutoff))) (filter first paths_to_remove)))
  ; (def paths_to_remove_2 (filter (fn [[[pid scr] ca]] (or true (> scr cutoff))) (filter first paths_to_remove)))

  ; (println "The paths to remove are: ")
  ; (pprint paths_to_remove_2)

  (.close result_img)

  ; this gives a list of [path_id score] to remove
  (set (map (comp first first) paths_to_remove_2)))
