(ns il.world
  (:require
   [il.util :refer [rand-int-range]]
   [clojure.math :as math]))

(defn- resource-size [amt]
  (cond 
    (>= amt 4000) "huge"
    (>= amt 2750) "large"
    (>= amt 1500) "medium"
    :else "small"))

(defn- in-water [water point]
  (let [[x y] point]))

(defn- rand-int-range-seq [min max]
  (repeatedly (partial rand-int-range min max)))

(def region-division 4)

;; I thought about using Perlin noise to generate the water, but I find it over kill.
;; Instead, we split the world width, world height by a "region size", and pick
;; a random coordinate in those to generate water.
(defn generate-water [world world-width world-height]
  (let [region-width  (/ world-width region-division)
        region-height (/ world-height region-division)
        water (reduce
               (fn [water [xs ys]]
                 (let [rw (* region-width xs)
                       rh (* region-height ys)]
                   (if (< (rand) 0.25) ; Only generate water in 25% of regions
                     (let [[wx wy] [(rand-int-range (- rw region-width) rw)
                                    (rand-int-range (- rh region-height) rh)]
                           spokes (rand-int-range 5 17) ; "spokes" are how many points around the initial water placement
                           points (reduce
                                   (fn [points [angle radius]]
                                     (let [sx (+ wx (* radius (math/cos angle)))
                                           sy (+ wy (* radius (math/sin angle)))]
                                       (conj points [(int sx) (int sy)])))
                                   []
                                   (mapv vector
                                         (sort (take spokes (rand-int-range-seq 0 (* math/PI 2))))
                                         (take spokes (rand-int-range-seq 6 12))))]
                       (conj water (conj points (first points)))) ; Append first point to end of vector, to complete the polygon
                     water)))
               []
               (for [xs (range 1 (inc region-division))
                     ys (range 1 (inc region-division))]
                 [xs ys]))]
    (assoc world :water water)))


(defn generate-resources [world resource-types min max world-width world-height]
  (let [resources (reduce
                   (fn [resources [type amt]]
                     (reduce
                      (fn [resources _]
                        (let [x (rand-int-range 0 world-width)
                              y (rand-int-range 0 world-height)
                              amt (rand-int-range 1000 5000)
                              size (resource-size amt)]
                          (if (in-water (:water world) [x y])
                            resources
                            (conj resources [x y type amt size]))))
                      resources
                      (range amt)))
                   []
                   (for [rt resource-types
                         amt (take
                              (count resource-types)
                              (repeatedly (partial rand-int-range min max)))]
                     [rt amt]))]
    (assoc world :resources resources)))
