(ns com.oly.static-sites.do-blog.pages.chess-board
  (:require
   [com.oly.static-sites.do-blog.pages.chess.movement
    :refer [fetch-selected-piece-moves valid-move?]]
   [com.oly.static-sites.do-blog.pages.chess.render
    :refer [calculate-black-white create-board enhance-board place-pieces-on-board]]

   [com.oly.static-sites.do-blog.pages.chess.state :refer [game-state start-state]]
   [com.oly.static-sites.do-blog.pages.chess.vstate :as v :refer [viking-start-state]]
   [com.oly.static-sites.ui-hiccup.interface :refer [board]]
   [reagent.core :as r]))

#_(def game-state-viking (r/atom {:board viking-start-state}))
(defn setup []
  (prn "register listener")
  (prn (.postMessage js/window/parent #js {:api "fromWidget",
                                    :action "supported_api_versions"}))

  (.addEventListener js/window "message"
                     (fn [event]
                       (prn "message")
                       (prn (.-origin event))
                       (prn (.-data event)))))

(defonce test-event (setup))

(defn square-defaults [pos]
  {:piece {}
   :bg-colour (name (calculate-black-white pos))
   #_(if (= (calculate-black-white pos) :black)
       "bg-slate-200 black-80"
       "bg-slate-800 white-80")})

(defn board-test [size]
  (loop [x-pos 1
         y-pos 1
         result []]
    (if (and (= x-pos size) (= y-pos size))
      result
      (if (= size x-pos)
        (recur 1
               (inc y-pos)
               (conj result [x-pos y-pos]))
        (recur (inc x-pos)
               y-pos
               (conj result [x-pos y-pos]))))))

(defn get-square [pos]
  (get @game-state [:board pos] {}))

(defn reset-square
  ([board pos] (reset-square board pos (square-defaults pos)))
  ([board pos value]
   (swap! board assoc-in [:board pos]  value)))

(defn update-square [pos value]
  (prn (str "update square " pos " " value))
  (swap! game-state update-in [:board pos]
         merge #_(get-in @game-state [:board pos] {})
         value))

(defn collisions [positions]
  (filterv (fn [[distance x y]]
             (let [piece (get-square [x y])]
               (prn (str "collision = " [x y] " - " (:type piece) " - " (:colour piece)))
               (and (nil? (:type piece))
                    (nil? (:colour piece))))) positions))

(defn highlight-moves [pos]
  (prn "highlight")
  (prn (fetch-selected-piece-moves
        (first (filter (fn [[k v]] (:selected v)) (-> @game-state :board)))
        (-> @game-state :board)))
  (->> (fetch-selected-piece-moves
        (first (filter (fn [[k v]] (:selected v)) (-> @game-state :board)))
        (-> @game-state :board))
       (mapv (fn [[distance x y]]
               (update-square
                [x y]
                {:highlight (str " bg-green-" (+ 2 distance) "00 ")
                 :pos [x y]})))))

(defn clear-keys [key]
  (swap! game-state
         assoc :board
         (reduce-kv (fn [m pos piece]
                      (assoc m pos (dissoc piece key))) {} (-> @game-state :board))))

(defn get-selected-square []
  (last (filter (fn [[_ square]] (true? (:selected square))) (-> @game-state :board))))

(defn piece-attribute-match?
  [src-piece dest-piece attrib]
  (prn (str "attrib " attrib " " (get src-piece attrib) " - " (get dest-piece attrib)))
  (if (and (:type dest-piece) (= (get src-piece attrib) (get dest-piece attrib)))
    true false))

(defn take-piece?
  "Check we actually have a piece and not an empty square
  Also check the colours do not match"
  [piece-one piece-two]
  (if (and (:type piece-two)
           (not= (:colour piece-one) (:colour piece-two)))
    true false))

(defn switch-player []
  (if (= (-> @game-state :player-one :selected) true)
    (do (swap! game-state assoc-in [:player-one :selected] false)
        (swap! game-state assoc-in [:player-two :selected] true))
    (do (swap! game-state assoc-in [:player-one :selected] true)
        (swap! game-state assoc-in [:player-two :selected] false))))

(defn current-player []
  (if (= (-> @game-state :player-one :selected) true)
    (-> @game-state :player-one)
    (-> @game-state :player-two)))

(defn move-piece
  [selected-piece dest-square]
  ;; check the colours don't match can't land on our own piece
  (if (piece-attribute-match? selected-piece dest-square :colour)
    nil
    (when
     (valid-move? (:pos dest-square) (-> @game-state :board))
      (prn "--------------")
      (switch-player)
      (when (take-piece? selected-piece dest-square)
        (prn (str "taking " dest-square))
        (prn (str "taking " (:colour dest-square)))
        (swap! game-state update (if (= :white (:colour selected-piece)) :player-one :player-two) conj dest-square))

      (prn "#####")
      (update-square (:pos dest-square) (merge dest-square {:piece  (assoc selected-piece :pos (:pos dest-square))}))
      (reset-square game-state (:pos selected-piece) (square-defaults (:pos selected-piece))))))

(defn click-square [evt p]
  (let [[selected-pos {selected-piece :piece} #_selected-piece] (get-selected-square)
        clicked-square p]
    (clear-keys :highlight)
    (when (piece-attribute-match? (current-player) selected-piece :colour)
      (when selected-pos
        (prn "previously selected piece")
        (move-piece selected-piece clicked-square)))

    (clear-keys :selected)
    (clear-keys :highlight)
  ;; set new square as selected
    (update-square (:pos p) (assoc (get-square (:pos p)) :selected true))
    (highlight-moves (:pos p))))

(defonce viking-chess-board-setup
  (reset! v/game-state
          {:player-one {:pieces []
                        :colour :white
                        :selected true}
           :player-two {:pieces []
                        :colour :black
                        :selected false}
           :board
           (-> (create-board 11 square-defaults)
               (enhance-board click-square)
               (place-pieces-on-board v/viking-start-state click-square))}))

(defonce chess-board-setup
  (reset! game-state
          {:player-one {:pieces []
                        :colour :white
                        :selected true}
           :player-two {:pieces []
                        :colour :black
                        :selected false}
           :board
           (-> (create-board 8 square-defaults)
               (enhance-board click-square)
               (place-pieces-on-board start-state click-square))}))

(defn chess-page [{:keys [path-params] :as route}]
  (fn [{:keys [path-params] :as route}]
    [:div
     (let [[pos piece] (get-selected-square)]
       [:div
        [:div (if (-> @game-state :player-one :selected)
                "Whites turn"
                "Black turn")]
        [:div "Player one " (str (mapv :type (-> @game-state :player-one :pieces)))]
        [:div "Player two " (str (mapv :type (-> @game-state :player-two :pieces)))]
        [:div (str "pos = " pos)]
        [:div (str (:type piece))]
        [:div (str piece)]
        [:div (str "move = " (fetch-selected-piece-moves
                              [pos piece]
                              (-> @game-state :board)))]])

     [:div (board 8 (-> @game-state :board))]
     [:div "Viking chess board"]
     [:div (board 11 (-> @v/game-state :board))]]))

(comment
  (get-selected-square)
  @game-state)


