; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.

; This script will present a dialog that allows the user to queue up
; a bunch of files for later, one-at-a-time processing.
;
; The script adds a new submenu, "File->Sequential Edit" containing
; three new commands. 

; "Choose Files..." presents a dialog which permits selecting the files
; that are to be queued up for editing. There are two components to this
; dialog. First, the user is able to select a base directory which contains
; the files, while the second is a list of filenames to be added to the 
; queue. Wildcard patterns can be specified to match multiple files (e.g.,
; *.jpg). The filename patterns should be separated by spaces, and 
; any filename containing spaces should be place within double quotes.
; If an absolute path is provided, the base directory specified is ignored
; for that particular pattern. 

; The "Save and open next" command will result in the file being saved 
; back to the original location, overwriting the original file. The image
; is then close and the next one in the queue opened.


; Note: if there is no image open when "Save and open next" is performed,
;       or the current image was not one that was queued up, then 
;       "Save and open next" will merely open the next file in the 
;       queue. This allows one to abandon edits in the current file
;       and yet continue editing the remaining queued files. 

(define (script-fu-sg-sequential-open dir pattern-string)
  (define (remove lis item)
    (let loop ((lis lis)
               (result '()) )
      (if (null? lis)
        (reverse result)
        (loop (cdr lis)
              (if (equal? (car lis) item)
                result
                (cons (car lis) result) )))))
  (define (set-prefix s dir)
    (if (equal? (make-string 1 (string-ref s 0)) DIR-SEPARATOR)
      s
      (string-append dir DIR-SEPARATOR s) ))
  ;; Starting with the second pattern, every other pattern
  ;; is a glob enclosed in quotes (most likely containing spaces).
  (let ((patterns 
          (let loop ((patterns (strbreakup pattern-string "\""))
                     (unquoteds '())
                     (quoteds '())
                     (no-quote #t) )
            (if (null? patterns)
              (append unquoteds quoteds)
              (loop (cdr patterns)
                    (if no-quote
                      (append unquoteds (remove (strbreakup (car patterns) " ") ""))
                      unquoteds )
                    (if no-quote
                      quoteds
                      (append quoteds (list (car patterns))) )
                    (not no-quote) )))))
    (let ((files (let loop ((patterns (if (pair? patterns)
                                        (map (lambda (x) (set-prefix x dir))
                                             patterns )
                                        '() ))
                            (filenames '()) )
                   (if (null? patterns)
                     filenames
                     (loop (cdr patterns)
                           (append filenames (cadr (file-glob (car patterns) 1))) )))))
      (gimp-parasite-detach "sequential-queue")
      (gimp-parasite-detach "sequential-display")
      (unless (null? files)
        (gimp-parasite-attach (list "sequential-queue" 
                                    2 
                                    (unbreakupstr (cdr files) ":") ))
        (let ((image (catch #f (car (gimp-file-load RUN-NONINTERACTIVE
                                                    (car files)
                                                    (car files) )))))
          (if image
            (gimp-parasite-attach 
              (list "sequential-display" 
                    2 
                    (string-append (number->string (car (gimp-display-new image)))
                                   ":"
                                   (car files) )))))))
    (gimp-progress-end) ))

(define (script-fu-sg-save-and-next)
  (define (find-opened-image filename)
    (let loop ((images (vector->list (cadr (gimp-image-list))))
               (image-id #f) )
      (if (null? images)
        image-id
        (loop (cdr images)
              (or image-id
                  (if (string=? filename 
                                (car (gimp-image-get-filename (car images))) )
                    (car images)
                    #f ))))))
  (let* ((prev-filename (catch #f 
                          (cadr (strbreakup (caddar (gimp-parasite-find 
                                                      "sequential-display" ))
                                            ":" ))))
         (prev-view 
           (catch #f (string->number
                       (car (strbreakup 
                              (caddar (gimp-parasite-find "sequential-display"))
                              ":" ))))) 
         (image (if prev-filename 
                  (find-opened-image prev-filename)
                  #f ))
         (saved? #f) )
      (catch #f (gimp-parasite-detach "sequential-display"))
      (when image
        (let ((ext (car (last (strbreakup prev-filename "."))))
              (layer #f) )
          (if (or (string-ci=? ext "gz") 
                  (string-ci=? ext "bz2")
                  (string-ci=? ext "xcf")
                  (string-ci=? ext "xcfgz")
                  (string-ci=? ext "xcfbz2") )
            (set! layer (car (gimp-image-get-active-layer image)))
            (set! layer (car (gimp-image-merge-visible-layers image CLIP-TO-IMAGE))) )
          (set! saved? (catch #f (car (gimp-file-save RUN-NONINTERACTIVE 
                                                      image 
                                                      layer
                                                      prev-filename 
                                                      prev-filename ))))))
      (let ((queue (catch #f (caddar (gimp-parasite-find "sequential-queue")))))
        (if queue
          (let ((files (strbreakup queue ":")))
            (gimp-parasite-detach "sequential-queue")
            (unless (null? (cdr files))
              (gimp-parasite-attach (list "sequential-queue"
                                          2
                                          (unbreakupstr (cdr files) ":") )))
            (let ((new-image (catch #f (car (gimp-file-load RUN-NONINTERACTIVE
                                                            (car files)
                                                            (car files) )))))
              (if (and image prev-view)
                (begin 
                  (gimp-displays-reconnect image new-image)
                  (gimp-parasite-attach 
                    (list "sequential-display" 
                          2 
                          (string-append (number->string prev-view)
                                         ":"
                                         (car files) ))))
                (begin
                  (gimp-parasite-attach 
                    (list "sequential-display" 
                          2 
                          (string-append (number->string (car (gimp-display-new new-image)))
                                         ":"
                                         (car files) )))))))))
      (unless saved?
        (gimp-message "Failed to save file") )
      (unless image
        (gimp-message "No image available for sequential edit") ))
  (gimp-displays-flush)
  (gimp-progress-end) ) 
      
(script-fu-register "script-fu-sg-sequential-open"
  "Choose Files..."
  "Open a set of files to edit one-at-a-time"
  "Saul Goode"
  "Saul Goode"
  "March 2014"
  ""
  SF-DIRNAME    "Directory"    "."
  SF-STRING     "Pattern"      "*.jpg"
  )

(script-fu-menu-register "script-fu-sg-sequential-open"
 "<Image>/File/Sequential Edit"
 )

(script-fu-register "script-fu-sg-save-and-next"
  "Save and Open Next"
  "Save current file, close it, and open next file in queue"
  "Saul Goode"
  "Saul Goode"
  "March 2014"
  ""
  )

(script-fu-menu-register "script-fu-sg-save-and-next"
 "<Image>/File/Sequential Edit"
 )


