#|

Search Session Object

TODO

The idea was I basically just wanted to copy the code from web/search.lisp

Maybe each database object could have their own search sessions? Like
the web deck builder could subclass SEARCH-SESSION with the correct
DEFAULT-INITARGS and relevant CLASS info

|#

(defpackage #:cl-deck-builder2.models.search
  (:use #:cl))

(in-package #:cl-deck-builder2.models.search)

;; TODO Where does this go?
(defparameter +search-param-whitelist+
  '("amazon-asin" "barcode" "brand" "buy-price" "category" "code" "created-by"
    "deck-id" "desc" "description" "domestic-only" "edition" "email" "id" "kind"
    "linkmarkers" "linkval" "manufacturer-sku" "max-qty" "msrp" "parent" "price"
    "product-name" "rarity" "rarity-code" "sell-price" "tax-exempt" "total-qty"
    "url" "weight" "wishlists" "atk" "def" "level" "scale" "passcode" "type"
    "frame-type" "race" "attribute" "archetype" "name" "opt-qty" "qty" "condition")
  "A whitelist of keywords allowed by user input on the database side.")

(defclass search-session-base () ())

;; TODO SLOTs or MAKE-HASH-TABLE? Or an ALIST?
(defclass search-session (search-session-base)
  ((direction)
   (limit)
   (offset)
   (sort-by)
   (variant))
  (:default-initargs
   :direction "asc"
   :limit 10
   :offset 0
   :sort-by "id"))

(defmethod initialize-instance :after ((obj search-session) &rest initargs &key &allow-other-keys)
  (declare (ignore initargs)))

;; FILTER-ALIST
(defgeneric search-query-filter (obj))

;; MAKE-SEARCH-QUERY
(defgeneric search-query-exec (obj))

;; MAKE-COUNT-QUERY
(defgeneric search-query-count (obj))

;; MAKE-ORDER-BY
(defgeneric search-query-order-by (obj direction sort-by))

;; MAKE-WHERE-CLAUSE
(defgeneric search-where-and (obj direction sort-by))
 
(defun make-sql-clause (op field value)
  (let ((op (typecase op
              (symbol op)
              (string (alexandria:make-keyword (string-upcase
                                                (substitute #\_ #\- op))))))
        (field (typecase field
                 (symbol field)
                 (string (alexandria:make-keyword (string-upcase
                                                   (substitute #\_ #\- field)))))))
    (list op field (if (eq op :like)
                       (format nil "%~a%" value)
                       value))))

;; (defun make-kind (kind alist))
