;;; -*- Mode: Lisp; Package: DESIGN; Syntax: Ansi-common-lisp -*-

;;; Use Model:  maps activity-labels to territories.  Use model is just a list of use-spaces;
;;; it's associated with a particular territory model.

;;; store use-models on related territory-model? for now, no.

(defclass USE-MODEL (basic-object territory-model-mixin)
  ((use-spaces :initform nil :initarg :use-spaces :accessor use-spaces)))

(defmethod initialize-instance :after ((model use-model) &rest plist)
  plist
  (save-model model))

(defun activity-label-choices ()
  '(:living :dining :semi-living :circulation :entry :cooking :service :storage :guest
	    :sleeping))

(defmethod add-use-space ((model use-model) space)
  (with-slots (use-spaces) model
    (pushnew space use-spaces)
    (setf (use-model space) model)))

(defmethod alternate-use-models ((model use-model))
  ;; other use-models for same territory-model
  (loop with territory-model = (territory-model model)
	for umodel in (get-use-models)
	when (eq (territory-model umodel) territory-model)
	  collect umodel))


;; Use-space may cover more than one territory; assume the territories are adjacent and
;; disjoint (simplifies finding perimeter).  Territory is the union of territories;
;; represents perimeter of use-space.  Use territory for calculations.  What about finding
;; paths, which uses circulation model built using underlying territories?

;; Probably should add privacy labels (e.g. public, private, semi-private).  Later.

(defclass USE-SPACE (basic-object territories-mixin)
  ((activity-labels :initform nil :initarg :activity-labels :accessor activity-labels)
   (use-model :initform nil :initarg :use-model :accessor use-model)
   (territory :initform nil :initarg :territory :accessor territory)))

(defun make-use-space (plist &optional tmodel)
  (let ((territory (getf plist :territory)))
    (when (typep territory 'symbol)
      (setf (getf plist :territory) (find-territory territory tmodel))))
  (apply #'make-instance 'use-space plist))

;; add use-model and territories...
(defmethod plist-for-save append ((space use-space))
  (with-slots (activity-labels level) space
    `(:activity-labels ,activity-labels)))

(defmethod territory-model ((space use-space))
  (with-slots (use-model) space
     (territory-model use-model)))

#|
;; +++ What's the semantics now? find contiguous use-spaces?  contiguous territories?
;; Do territories point to use-spaces?  These methods assume there's a way to get from
;; territories to use-spaces.

;; opening between
(defmethod contiguous-spaces ((space use-space))
  ;; use predicate to pass in type info; e.g. #'(lambda (x) (widep x))
  (mapcar #'use-space-for-territory (contiguous-territories (territory space))))

;; adjacent
(defmethod neighboring-spaces ((space basic-space))
  (mapcar #'use-space-for-territory (neighboring-territories (territory space))))

(defun contiguous-exterior-spaces (space) 
  (loop for s in (contiguous-spaces space)
	when (exteriorp s) collect s))

(defun neighboring-exterior-spaces (space)
  (loop for s in (neighboring-spaces space)
	when (exteriorp s) collect s))

|#





