(in-package :cl-blog)

(defvar *blog-entries* nil)
(defvar *blog-entry-counter* 0)

(defvar *trackbacks* nil)
(defvar *trackback-counter* 0)

(define-simple-serialized-class blog-entry ()
  ((category :initarg :category :accessor blog-entry-category)
   (user :initarg :user :accessor blog-entry-user)
   (number :initarg :number :accessor blog-entry-number)
   (title :initarg :title :accessor blog-entry-title)
   (time :initarg :time :accessor blog-entry-time)
   (revised-time :initarg :revised-time :initform 0 :accessor blog-entry-revised-time)
   (contents :initarg :contents :accessor blog-entry-contents)
   (trackbacks :initarg :trackbacks :accessor blog-entry-trackbacks :initform nil)
   (permalink :initarg :permalink :accessor blog-entry-permalink))
  (:store *blog-entries*)
  (:store-directory *entry-path*)
  (:key-slot number))

(defmethod blog-entry-number :around ((entry blog-entry))
  (if (not (slot-boundp entry 'number))
      0
      (call-next-method)))

(define-simple-serialized-class trackback ()
  ((number :initarg :number :accessor trackback-number)
   (title :initarg :title :accessor trackback-title)
   (url :initarg :url :accessor trackback-url)
   (excerpt :initarg :excerpt :accessor trackback-excerpt)
   (time :initarg :time :accessor trackback-time)
   (blog-name :initarg :blog-name :accessor trackback-blog-name))
  (:store *trackbacks*)
  (:store-directory *trackback-path*)
  (:key-slot number))

(defclass administrator ()
  ())

(defvar *users* (list (make-instance 'administrator)))

(define-simple-serialized-class user ()
  ((name :initarg :name :accessor user-name)
   (display-name :initarg :display-name :accessor user-display-name)
   (description :initarg :description :accessor user-description)
   (link :initarg :link :accessor user-link)
   (password :initarg :password :accessor user-password)
   (disabled-p :initarg :disabled-p :accessor user-disabled-p :initform nil))
  (:store *users*)
  (:store-directory *user-path*)
  (:key-slot name))

(defmethod user-name ((user administrator))
  *administrator*)

(defmethod user-display-name ((user administrator))
  "Our Fearless Leader")

(defmethod user-description ((user administrator))
  "Rarely seen, oft needed, the administrator is in charge of breaking and fixing the blog.")

(defmethod user-link ((user administrator))
  (concatenate 'string "mailto:" *owner-email*))

(defmethod user-password ((user administrator))
  *administrator-password*)

(defmethod user-disabled-p ((user administrator))
  nil)

(defmethod print-object ((object administrator) stream)
  (format stream "#.(~S ~S)"
          'cl-blog::find-user
          'cl-blog::*administrator*))

(defun find-user (user)
  (find user *users* :test #'string-equal :key #'user-name))

(defmethod key-of-instance ((instance administrator))
  (user-name instance))