#!/bin/sh
: ; exec klone $0 "$@"
; The above line allows not to embed the exact path of the klone executable

;;Skeleton of a typical klone script

(setq args (getopts "USAGE: %0 [options] dir...
Cleans all generic NFOs in dirs, recursively
Known generic NFOs must be put in the directory ~/.nfos (which must exist)
The base of nfos is maintained in the subdir .saved there
nfos found in ~/.nfos are stored into it at each run of the program

Usage: when you find generic .nfo files that you want to remove, put them 
(move them) into your ~/.nfos dir. Then nfo-clean will be able to detect and
remove them in your dirs. Add then the unremoved ones to ~/.nfos ...
(You can also move them there by %0 -a)

In ~/.nfos/re/, you can put regexps of files to examine (of max size 32)
as files containing each a klone p-list (p-vector) of strings, with keys 
:fixed, :re, or :re-nocase if the strings are literal, case-dependent or 
case-independent regexps. (beware to delimit newlines by \r?\n)
Do not mark ends (^ or $) in regexps, they will be added automatically.
e.g.: [:fixed \"a header\" :re \"variant part\" :fixed \"trailer\"]
"
    ("-a" () only-add "only add rest of args (.nfos) to database")
    ("-q" () quiet "quiet operation, otherwise verbose")
    ("-u" () only-update "only update the database, do not clean dirs")
    ("-debug" () enter-debugger-on-error "enter klone debugger on error"
 :hidden t)
    ("-stackdump" () stackdump-on-error "verbose stack dump on error"
 :hidden t)
))

(setq re-size-max 32768)
(if enter-debugger-on-error (kdb t))
(if stackdump-on-error (stack-dump-on-error t))
(setq verbose (not quiet))

(if (not args) (if (not only-update) (getopts :usage)))

(setq NFOS (Hashtable ()))		;HT of sizes / bodies list
(setq RES (vector))			;list of regexps

(defun main (&aux
  )
  (when only-add (move-nfos args) (setq only-update t))
  (parse-nfos)
  (if (not only-update)
    (dolist (dir args)
      (clean-nfos-dir dir)
)))

(defun parse-nfos (&aux desc end?)
  (if (/= 'directory (file-type "~/.nfos")) (progn
      (PF "*** Creating your ~/.nfos dir. Then, put your found .nfos there\n")
      (sh rm -rf "--" "~/.nfos")
      (sh mkdir "~/.nfos")
  ))
  (with (*current-directory* "~/.nfos" body () size ())
    ;; create base if not here
    (if (/= 'directory (file-type ".saved")) (sh "rm -rf .saved;mkdir .saved"))
    (if (/= 'directory (file-type "re")) (sh "rm -rf re;mkdir re"))

    ;; store new nfos in database
    (dolist (nfo (directory))
      (if (and (/= nfo "re") (/= nfo ".saved"))
	(add-nfo nfo)
    ))
    ;; parse regexps
    (with (*current-directory* "re" re ())
      (dolist (nfo (directory))
	(setq end? t)
	(setq desc (read (open nfo)))
	(setq re (copy "^")) 
	(dohash (key s desc)
	  (if (= key :fixed) (nconc re (quote-string-for-regexp s :crlf t))
	    (= key :re) (nconc re s)
	    (= key :re-nocase) (nconc re (re-nocase s))
	    (= key :end) (setq end? ())	;undocumented, match only on beginning
	    t (fatal-error 1 
	      "Aborting, Bad re syntax \"%1\" in file: ~/.nfos/re/%0\n"
	      nfo key
	)))
	(if end? (nconc re "$"))
	(lappend RES (regcomp re))
    ))
    ;; parse nfos in database
    (with (*current-directory* ".saved")
      (dolist (nfo (directory))
	(setq body (String (open nfo)))
	(setq size (length body))
	(if (getn NFOS size)
	  (lappend (getn NFOS size) body)
	  (put NFOS size (vector body))
      ))
      (verbose? "Database of %0 .nfo and %1 re/ files read"
	(length (directory)) (length RES))
    )
))

(defun move-nfos (files &aux (nfo-dir (expand-filename "~/.nfos")))
  (dolist (file files)
    (verbose? "Moving %0 in ~/.nfos" file)
    (wait (system (list "mv" file nfo-dir)))
  )
)

(defun add-nfo (file &aux (sf (+ ".saved/" file)))
  (while (and (file-stats sf) (not (file-equal file sf)))
    (setq sf (+ sf "o"))
  )
  (sh chmod a+rw ,file)
  (if (file-equal file sf)
    (progn
      (verbose? "Not adding %0, already in base" file)
      (sh rm -f "--" ,file)
    )
    (progn
      (if (/= sf (+ ".saved/" file))
	(verbose? "Add/tmp/nfos2/MidGaard.nfoing %0 to database of .nfos as %1" file sf)
	(verbose? "Adding %0 to database of .nfos" file)
      )
      (sh mv ,file ,sf)
    )
  )
)

(defun file-equal (f1 f2)
  (and 
    (= (getn (file-stats f1) 'size) (getn (file-stats f2) 'size))
    (= (String (open f1)) (String (open f2)))
  )
)

(defun clean-nfos-dir (topdir &aux
    bodies body 
  )
  (if ({regcomp "(^|[/]).nfos$"} topdir)
    (PF "*** Refusing to process %0, you may erase your database!\n" topdir)
    (dofile (file stats dir topdir)
      (catch 'ERROR
	(catch 'Removed
	  (setq body ())
	  (when (setq bodies (getn NFOS (getn stats 'size)))
	    (if (not body) (setq body (String (open file))))
	    (dolist (b bodies)
	      (when (= body b)
		(verbose? "Removing %0" (concat-paths dir file))
		(sh rm -f "--" ,file)
		(throw 'Removed)
	  )))
      ;; dont try REs on big files
	  (when (< (getn stats 'size) re-size-max)
	    (if (not body) (setq body (String (open file))))
	    (dolist (re RES)
	      (when (re body)
		(verbose? "Removing %0 (matches regexp)" 
		  (concat-paths dir file))
		(sh rm -f "--" ,file)
		(throw 'Removed)
	))))
))))

(main)

;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***

