#!/usr/bin/env tclsh

package req nx::doc 1.0

namespace eval ::nx::doc {
  namespace import -force ::nx::*
  Class create CLI {
    
    #
    # rendering
    #
    :property {outdir "."}
    :property {format "html"}
    :property {theme "yuidoc"}
    :property {layout "many-to-many"}
    
    #
    # doc project
    #
    :property doctitle
    :property {docversion 0.1}
    :property docurl
    :property docbaseurl
    :property {validation:switch false}
    
    #
    # frontend
    #
    :property {frontend dc}
    :property includes
    :property excludes
    :property indexfiles:alias

    :protected property sources:1..* {
      set :incremental 1
      set :config false
    }

    #
    # auxiliary 
    #

    :private method barf {msg} {
      return -code error "NXDoc: $msg"
    }

    :protected method ... args {
      foreach i $args {
	set idx [string first : $i]
	if {$idx == -1} continue;
	dict lappend :sources [string range $i 0 [expr {$idx - 1}]] [string range $i [expr {$idx + 1}] end]
      }
    }

    :protected method indexfiles {paths} {
      #
      # TODO: Should we provide for an auto-lookup of nxdocIndex files,
      # similar to tclIndex or pkgIndex.tcl?
      #

      #
      # Some sanity checks first ...
      #
      set sources [list]
      foreach p $paths {
	set p [file normalize $p]
	if {[file exists $p] && [file readable $p]} {
	  lappend sources [list source $p]
	} else {
	  : -local barf "Cannot find or read the index file '$p'"
	}
      }
      
      if {$sources eq ""} return;
      
      set i [interp create]
      $i eval {
	proc ::unknown args { puts stderr "UNKNOWN: $args"}
	namespace eval ::nxdoc::internal {
	  proc getIndexedCmds {{choice 0}} {
	    if {[array exists ::nxdoc::include]} {
	      array set out [list 0 "" 1 ""]
	      foreach {v cmd} [lreverse [array get ::nxdoc::include]] {
		lappend out($v) $cmd
	      }
	      return [lindex [array get out $choice] 1]
	    }
	  }
	}
      }
      if {[catch {$i eval [join $sources ";"]} err]} {
	: -local barf "Sourcing index files failed with error message '$err'"
      }
      
      lappend :includes {*}[$i eval [list ::nxdoc::internal::getIndexedCmds 1]]
      interp delete $i
    }

    :protected method __objectparameter {} {
      set slots [[current class] info slots]
      foreach slot $slots {
	lappend defs([$slot position]) [$slot getParameterSpec]
      }
      set parameterdefinitions [list]
      foreach p [lsort [array names defs]] {
	lappend parameterdefinitions {*}$defs($p)
      }
      return [concat $parameterdefinitions ...:alias,args]
    }
    
    :protected method init {} {

      set prj [@project newFromSources \
		   -frontend ${:frontend} \
		   {*}[expr {[info exists :includes]?[list -include ${:includes}]:""}] \
		   {*}[expr {[info exists :excludes]?[list -exclude ${:excludes}]:""}] \
		   ${:sources} \
		   -name ${:doctitle} \
		   -url ${:docurl} \
		   -version ${:docversion} \
		   {*}[expr {${:validation}?"-mixin ::nx::doc::@project::Validator":""}]]
      

      
      $prj write -format ${:format} -theme ${:theme} -layout ${:layout} -outdir ${:outdir}
    }
  }
  namespace export CLI
}

namespace import -force ::nx::doc::CLI
#
# nxdoc -outdir /tmp/ -format html -theme yuidoc package:nsf
#
CLI new {*}$argv