#lang racket/base

(require
  "stored-objects.rkt"
  "user.rkt"
  )

(provide
  ; Accessors
  note-name note-title note-author note-date note-content note-licence note-public?
  ; Operations
  new-note update-note remove-note
  get-note-by-name get-all-notes get-public-notes
  ; Init repo
  note-init-repository
  )

; Note structure
(stored-class notepadnote
  (name : string?) ; Name of the note, used for the URI (metadata)
  (title : string?) ; title of note (metadata)
  (author : integer?) ; author of last update (metadata), id of user
  (content : string?) ; content of the note (raw format)
  (date : integer?) ; date of last update (metadata)
  (licence : string?) ; Licence of the note (metadata)
  (public : boolean?) ; Public note ? (metadata)
  )

; Repo initialization
(define (note-init-repository repo)
  (init-repository repo
    notepadnote))

; Accessors
(define note-name notepadnote-name)
(define note-title notepadnote-title)
(define (note-author nt)
  (define author (get-user-by-id (notepadnote-author nt)))
  (and author (user-pseudo author)))
(define (note-date nt)
  (define dt (seconds->date (notepadnote-date nt)))
  (define (add-zero x)
    (if (< x 10)
        (string-append "0" (number->string x))
        x))
  (format "~a-~a-~a"
    (date-year dt)
    (add-zero (date-month dt))
    (add-zero (date-day dt))))
(define note-content notepadnote-content)
(define note-licence notepadnote-licence)
(define note-public? notepadnote-public)

; Note Operations

; New note
(define (new-note
          #:name name
          #:title title
          #:author author
          #:content content
          #:licence (licence #f)
          #:public? (public? #f))
  (within-transaction (class-repository notepadnote)
    (define nt (instanciate notepadnote))
    (set-notepadnote-name! nt name)
    (set-notepadnote-title! nt title)
    (set-notepadnote-author! nt (instance-identifier author))
    (set-notepadnote-content! nt content)
    (set-notepadnote-date! nt (current-seconds))
    (set-notepadnote-licence! nt licence)
    (set-notepadnote-public! nt public?)
    (save-instance nt)
    nt))

; Update note. If nt is #f, create a new note.
(define (update-note nt
          #:name name
          #:title title
          #:author author
          #:content content
          #:licence (licence #f)
          #:public? (public? #f)
          )
  (within-transaction (class-repository notepadnote)
    (define new-nt (or nt (instanciate notepadnote)))
    (set-notepadnote-name! new-nt name)
    (set-notepadnote-title! new-nt title)
    (set-notepadnote-author! new-nt (instance-identifier author))
    (set-notepadnote-content! new-nt content)
    (set-notepadnote-date! new-nt (current-seconds))
    (set-notepadnote-licence! new-nt licence)
    (set-notepadnote-public! new-nt public?)
    (save-instance new-nt)
    new-nt))

; Remove a note
(define (remove-note nt)
  (within-transaction (class-repository notepadnote)
    ; Remove note
    (delete-instance nt)))

; Find by name
(define (get-note-by-name name)
  (define notes (find-instances notepadnote `((name . ,name))))
  (and (not (null? notes))
       (car notes)))

; Get all notes
(define (get-all-notes)
  (list-instances notepadnote))

; Get all public notes
(define (get-public-notes)
  (find-instances notepadnote '((public . #t))))
