(ns cc.journeyman.the-great-game.buildings.rectangular
  "Build buildings with a generally rectangular floow plan.
   
   ## Motivations
   
   Right, the idea behind this namespace is many fold.

   1. To establish the broad principle of genetic buildings, by creating a
      function which reproducibly creates reproducible buildings at specified
      locations, such that different buildings are credibly varied but a
      building at a specified location is always (modulo economic change) the
      same.
   2. Create good rectangular buildings, and investigate whether a single 
      function can be used to create buildings of more than one family (e.g.
      can it produce flat roofed, north African style, mud brick houses as
      well as pitch roofed, half timbered northern European houses?)
   3. Establish whether, in my current state of fairly severe mental illness,
      I can actually produce any usable code at all.

   ## Key factors in the creation of a building

   ### Holding

   Every building is on a holding, and, indeed, what I mean by 'building' here
   may well turn out to be 'the collection of all the permanent structures on
   a holding. A holding is a polygonal area of the map which does not 
   intersect with any other holding, but for the time being we'll make the 
   simplifying assumption that every holding is a rectangular strip, and that
   'urban' holdings are of a reasonably standard width (see Viking-period 
   York) and length. Rural holdings (farms, ?wood lots) may be much larger.

   ### Terrain

   A building is made of the stuff of the place. In a forest, buildings will 
   tend to be wooden; in a terrain with rocky outcrops -- normally found on 
   steep slopes -- stone. On the flat lands where there's river mud, of brick,
   cob, or wattle and daub. So to build a building we need to know the 
   terrain. Terrain can be inferred from location but in practice this will 
   be computationally expensive, so we'll pass terrain in as an argument to
   the build function.

   For the time being we'll pass it in simply as a keyword from a defined set
   of keywords; later it may be a more sophisticated data structure.

   ### Culture

   People of different cultures build distinctively different buildings, even
   when using the same materials. So, in our world, a Japanese wooden house 
   looks quite different from an Anglo Saxon stave house which looks quite 
   different from a Canadian log cabin, even though the materials are much the
   same and the tools available to build with are not much different.

   Culture can affect not just the overall shape of a building but also its 
   finish and surface detail. For example, in many places in England, stone
   buildings are typically left bare; in rural Scotland, typically painted 
   white or in pastel shades; in Ireland, often quite vivid colours.

   People may also show religious or cultural symbols on their buildings.
 
   For all these reasons, we need to know the culture of the occupant when
   creating a building. Again, this will initially be passed in as a keyword.

   ### Craft

   People in the game world have a craft, and some crafts will require 
   different features in the building. In the broadly late-bronze-age-to
   medieval period within which the game is set, residence and  workplace
   are for most people pretty much the same.

   So a baker needs an oven, a smith a forge, and so on. All crafts who do
   some degree retail trade will want a shop front as part of the ground 
   floor of their dwelling. Merchants and bankers will probably have houses
   that are a bit more showy than others.

   Whether the 'genetic buildings' idea will ever really produce suitable
   buildings for aristons I don't know; it seems more likely that significant
   strongholds (of which there will be relatively few) should all be hand
   modelled rather than procedurally generated."
  (:require [cc.journeyman.the-great-game.holdings.holding :refer [ProtoHolding]]
            [cc.journeyman.the-great-game.location.location :refer [ProtoLocation]])
  (:import [org.apache.commons.math3.random MersenneTwister]))

 
(def ^:dynamic *terrain-types* 
  "Types of terrain which affect building families. TODO: This is a placeholder;
   a more sophisticated model will be needed."
  #{:arable :arid :forest :plateau :upland})

(def ^:dynamic *cultures*
  "Cultures which affect building families. TODO: placeholder"
  #{:ariston :coastal :steppe-clans :western-clans :wild-herd})

(def ^:dynamic *crafts*
  "Crafts which affect building types in the game. See 
   `Populating a game world`. TODO: placeholder"
  #{:baker :banker :butcher :chancellor :innkeeper :lawyer :magus :merchant :miller :priest :scholar :smith :weaver})

(def ^:dynamic *building-families* 
  "Families of buildings.
   
   Each family has
   
   * terrain types to which it is appropriate;
   * crafts to which it is appropriate;
   * cultures to which it is appropriate. 
   
   Each generated building will be of one family, and will comprise modules 
   taken only from that family."
  {:pitched-rectangular {:terrains #{:arable :forest :upland}
                         :crafts *crafts*
                         :cultures #{:coastal :western-clans}
                         :modules []}
   :flatroof-rectangular {:terrains #{:arid :plateau}
                          :crafts *crafts*
                          :cultures #{:coastal}
                          :modules []}})


(defn building-family
  "A building family is essentially a collection of models of building modules
   which can be assembled to create buildings of a particular structural and
   architectural style."
  [terrain culture craft gene]
  (let [candidates (filter #(and
                             ((:terrains %) terrain)
                             ((:crafts %) craft)
                             ((:cultures %) culture))
                           (vals *building-families*))]
    (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates)))))

(building-family :arable :coastal :baker (MersenneTwister. 5))

(defn build! 
  "Builds a building, and returns a data structure which represents it. In 
   building the building, it adds a model of the building to the representation
   of the world, so it does have a side effect."
  [holding terrain culture craft size]
  (if (satisfies? ProtoHolding holding)
  (let [location (.building-origin holding)
        gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location))))
        family (building-family terrain culture craft gene)]
  (if 
   (and (instance? ProtoLocation location) (:orientation location))
    :stuff
    :nonsense
    ))
    :froboz))

;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))

