/**
= Creative Commons Lizenzvertrag =
Diese Software ist von der archium GmbH, Gera ist lizenziert unter einer Creative Commons Namensnennung - Nicht kommerziell - Keine Bearbeitungen 4.0 International Lizenz. (http://creativecommons.org/licenses/by-nc-nd/4.0/deed.de)
Individuelle über diese Lizenz hinausgehende Berechtigungen können Sie unter https://archium.org erhalten.

= Creative Commons License =
Software by archium GmbH, Gera is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Individual permissions beyond the scope of this license may be available at https://archium.org.
**/

package main // import "Toolbox"

import (
	"errors"
	"fmt"
	"html"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"time"

	json "encoding/json"
	//
	_ "github.com/lib/pq"
	gjs "github.com/tidwall/gjson"

	//
	def "Toolbox/defaults"
	god "Toolbox/goDataverse"
	svg "Toolbox/goDataverse/svg"
	tol "Toolbox/goDataverse/tools"
	pog "Toolbox/postgres"

	// sch "Toolbox/goDataverse/search"
	// dst "Toolbox/goDataverse/dataset"
	// dvr "Toolbox/goDataverse/dataverse"
	// usr "Toolbox/goDataverse/user"
	//
	"Toolbox/goMetrix"
)

const (
	addr  = "pdp.archium.org"
	token = "f6933c5d-8e97-4e7a-b21a-c57447cca421"
)

// #############################################################################
// newFileSystem - handling
// #############################################################################
type newFileSystem struct {
	fs http.FileSystem
}

func (nfs newFileSystem) Open(path string) (http.File, error) {
	//log.Println("path ( load ):", path)
	f, err := nfs.fs.Open(path)
	if err != nil {
		log.Println("path ( error ):", path, err)
		return nil, err
	}
	//
	s, err := f.Stat()
	if s.IsDir() {
		if path == "/" {
			index := filepath.Join(path, "index.html")
			log.Println("path ( not opened ):", path, index, err)
			if _, err := nfs.fs.Open(index); err != nil {
				closeErr := f.Close()
				if closeErr != nil {
					return nil, closeErr
				}
				//
				return nil, err
			}
		}
	}
	//
	return f, nil
}

// #############################################################################
// get generic templates as TJson
// #############################################################################
func getEmpty() {
	if err := recover(); err != nil {
		def.LogError("getEmpty(recover)", errors.New("Cannot recover()."))
	}
	return
}

func getProject(_r *http.Request, _fvp tol.TFVParams, _what, _sql, _project string) (string, error) {
	// leeres ergebnis bei fehler
	defer getEmpty()
	var empty string = def.DEF_project
	//
	conn, err := pog.GetConnection()
	if err != nil {
		def.LogError("GetConnection()", err)
		return empty, err
	}
	defer pog.CloseConnection(conn)
	err = pog.PingConnection(conn)
	if err != nil {
		def.LogError("PingConnection()", err)
		return empty, err
	}
	if _fvp.FP_what == "" {
		_fvp.FP_what = _what
	}
	psqlSql := strings.ReplaceAll(_sql, "%schema%", def.DEF_schema)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablecustomer%", def.DEF_tablecustomer)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablelayout%", def.DEF_tablelayout)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablecontent%", def.DEF_tablecontent)
	psqlSql = strings.ReplaceAll(psqlSql, "%customerid%", strconv.Itoa(def.DEF_customerid))
	psqlSql = strings.ReplaceAll(psqlSql, "%type%", _fvp.FP_what)
	rows, err := conn.Query(psqlSql)
	if err != nil {
		def.LogError("Query()", err)
		return empty, err
	}
	defer rows.Close()
	cols, err := rows.Columns()
	if err != nil {
		def.LogError("Columns(rows)", err)
		return empty, err
	}
	// we"ll need to pass an interface to sql.Ro_w.Scan
	colvals := make([]interface{}, len(cols))
	var k = 0
	for rows.Next() {
		colassoc := make(map[string]interface{}, len(cols))
		for i, _ := range colvals {
			colvals[i] = new(interface{})
		}
		if err := rows.Scan(colvals...); err != nil {
			def.LogError("Scan(rows)", err)
			return empty, err
		}
		k += 1
		for i, col := range cols {
			colassoc[col] = *colvals[i].(*interface{})
		}
		if colassoc[_project] != nil {
			empty = colassoc[_project].(string)
		}
		//
		return empty, nil
	}
	//
	return def.DEF_project, nil
}

func getTemplate(_method string, _fvp tol.TFVParams, _sql string, _fieldlist []string) (tol.ColMap, error) {
	var resultlist tol.ColMap = make(tol.ColMap, 0)
	// leeres ergebnis bei fehler
	defer getEmpty()
	//
	conn, err := pog.GetConnection()
	if err != nil {
		def.LogError("getTemplate(sql.Open)", err)
		return resultlist, err
	}
	defer pog.CloseConnection(conn)
	err = pog.PingConnection(conn)
	if err != nil {
		def.LogError("getTemplate(sql.Ping)", err)
		//
		return resultlist, err
	}
	psqlSql := strings.ReplaceAll(_sql, "%schema%", def.DEF_schema)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablecustomer%", def.DEF_tablecustomer)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablelayout%", def.DEF_tablelayout)
	psqlSql = strings.ReplaceAll(psqlSql, "%tablecontent%", def.DEF_tablecontent)
	psqlSql = strings.ReplaceAll(psqlSql, "%customerid%", strconv.Itoa(def.DEF_customerid))
	psqlSql = strings.ReplaceAll(psqlSql, "%type%", _fvp.FP_what)
	rows, err := conn.Query(psqlSql)
	// log.Println("getTemplate(", _method, _fvp.FP_what, ") > "+psqlSql)
	if err != nil {
		// log.Println("(", _r.Method, ") > "+psqlSql)
		def.LogError("getTemplate(db.Query)", err)
		return resultlist, err
	}
	defer rows.Close()
	cols, err := rows.Columns()
	if err != nil {
		def.LogError("getTemplate(db.Columns)", err)
		return resultlist, err
	}
	// we"ll need to pass an interface to sql.Ro_w.Scan
	colvals := make([]interface{}, len(cols))
	var k = 0
	for rows.Next() {
		colassoc := make(map[string]interface{}, len(cols))
		for i, _ := range colvals {
			colvals[i] = new(interface{})
		}
		if err := rows.Scan(colvals...); err != nil {
			def.LogError("Scan(rows)", err)
			return resultlist, err
		}
		k += 1
		for i, col := range cols {
			colassoc[col] = *colvals[i].(*interface{})
		}
		for _, value := range _fieldlist {
			if len(value) > 0 {
				if colassoc[value] != nil {
					// log.Println("(", _method, ") > : ", key, value, colassoc[value].(string))
					resultlist[value] = colassoc[value].(string)
				}
			}
		}
		//
		return resultlist, nil
	}
	//
	return resultlist, nil
}

var DParamold string = ""
var DParam string = ""

func getDataParams(_r *http.Request) tol.TDVParams {
	dvp := new(tol.TDVParams)
	//
	DParam = _r.RequestURI
	// if DParam != DParamold {
	u, err := url.Parse(_r.RequestURI)
	if err != nil {
		def.LogError("getDataParams(parse)", err)
	}
	// log.Println("(", _r.Method, ") > Dataparams:", dvp)
	t := reflect.TypeOf(dvp).Elem()
	v := reflect.ValueOf(dvp).Elem()
	queries := u.Query()
	if len(queries) > 0 {
		for i := 0; i < v.NumField(); i++ {
			n := t.Field(i)
			f := v.Field(i)
			//log.Println("(", _r.Method, ") > Dataparams: type: ", t, n)
			f.SetString("")
			for key, values := range queries {
				if n.Name == "DP_"+key {
					// log.Println("(", _r.Method, ") > Dataparams: search > Values: ", key, "==", n.Name)
					for _, value := range values {
						f.SetString(value)
						break
					}
					break
				}
			}
		}
		if len(dvp.DP_localeCode) == 0 {
			dvp.DP_localeCode = "en"
		}
		DParamold = DParam
	}
	//log.Println("(", _r.Method, ") > Dataparams: success > Values: ", *dvp)
	// }
	return *dvp
}

func getFormparams(_r *http.Request) tol.TFVParams {
	fvp := new(tol.TFVParams)
	// log.Println("(", _r.Method, ") > Formparams:", fvp)
	//
	t := reflect.TypeOf(fvp).Elem()
	v := reflect.ValueOf(fvp).Elem()
	for i := 0; i < v.NumField(); i++ {
		n := t.Field(i)
		s := strings.Replace(n.Name, "FP_", "", -1)
		switch n.Type.String() {
		case "string":
			f := v.Field(i)
			f.SetString(_r.FormValue(s))
			//
			//log.Println("(", _r.Method, ") > Formparams: > field: ", strings.Replace(n.Name, "FP_", "", -1), f)
			break
		case "bool":
			// 	log.Println("(", _r.Method, ") > Formparams: > field: ", strings.Replace(n.Name, "FP_", "", -1), f)
			f := v.Field(i)
			f.SetBool((_r.FormValue(s) == "true"))
			// log.Println("(", _r.Method, ") > Formparams: > field: ", f, n, reflect.TypeOf(_r.FormValue(s)))
		}
	}
	fvp.FP_qery = ""
	//log.Println("(", _r.Method, ") > Formparams: ", fvp)
	//
	var params tol.ColMapInt = make(tol.ColMapInt, 0)
	//
	var strqry string = ""
	var strcnt int64 = 0
	var sumcnt int64 = 0
	// parm := _r.URL.Query()
	for keys, values := range _r.Form { // range over map
		if strings.Contains(keys, "parm") {
			if strings.Contains(keys, "search") {
				for _, ival := range values {
					def.LogMessage("getFormparams()", fmt.Sprintf("> %v: Formsearch: success > parm: %v", _r.Method, ival), def.DEF_logdebg)
					skey := ival[:strings.IndexByte(ival, '=')]
					sval := tol.GetstringBetween(ival, `{`, `}`)
					var andqry string = ""
					var andcnt int64 = 0
					if len(sval) > 0 {
						arrval := strings.Split(sval, ";")
						def.LogMessage("getFormparams({})", fmt.Sprintf("> %v: Formsearch: success > parm: %v", _r.Method, ival), def.DEF_logdebg)
						if len(arrval) > 0 {
							for _, aval := range arrval {
								if andcnt > 0 {
									andqry = andqry + ` OR `
								}
								andqry = andqry + skey + `:"` + strings.Replace(strings.Trim(aval, " "), `"`, ``, -1) + `"`
								andcnt = andcnt + 1
							}
							if andcnt > 0 {
								if andcnt > 1 {
									andqry = "(" + strings.TrimSpace(andqry) + ")"
								}
								if strcnt > 0 {
									strqry = strqry + ` AND `
								}
								strqry = strqry + andqry
								strcnt = strcnt + 1
							}
						}
					} else {
						stmp := ival[:strings.IndexByte(ival, '=')]
						if stmp == "fileDescription" {
							continue
						}
						sval := tol.GetstringBetween(ival, "[", "]")
						// erst nach "+" schauen ( AND )
						if len(sval) > 0 {
							arrval := strings.Split(sval, "+")
							if len(arrval) > 1 {
								for _, aval := range arrval {
									if andcnt > 0 {
										andqry = andqry + ` AND `
									}
									andqry = andqry + skey + `:"` + strings.Replace(strings.Trim(aval, " "), `"`, ``, -1) + `"`
									andcnt = andcnt + 1
								}
								if andcnt > 0 {
									if andcnt > 1 {
										andqry = "(" + andqry + ")"
									}
									if strcnt > 0 {
										strqry = strqry + ` AND `
									}
									strqry = strqry + andqry
									strcnt = strcnt + 1
								}
								def.LogMessage("getFormparams(and)", fmt.Sprintf("> %v: Formsearch: success > parm: %v, %v", _r.Method, andcnt, andqry), def.DEF_logdebg)
							} else {
								// wenn nicht, dann nach " " schauen ( OR )
								arrval := strings.Split(sval, " ")
								if len(arrval) > 0 {
									for _, aval := range arrval {
										if andcnt > 0 {
											// andqry = andqry + ` OR `
											andqry = andqry + ` `
										}
										andqry = andqry + skey + `:` + strings.Replace(strings.Trim(aval, " "), `"`, ``, -1)
										andcnt = andcnt + 1
									}
									if andcnt > 0 {
										if andcnt > 1 {
											andqry = "(" + strings.TrimSpace(andqry) + ")"
										}
										if strcnt > 0 {
											strqry = strqry + ` AND `
										}
										strqry = strqry + andqry
										strcnt = strcnt + 1
									}
									def.LogMessage("getFormparams(or)", fmt.Sprintf("> %v: Formsearch: success > parm: %v, %v", _r.Method, andcnt, andqry), def.DEF_logdebg)
								}
							}
						}
					}
					sumcnt += andcnt
				}
				if sumcnt > 0 {
					def.LogMessage("getFormparams(and)", fmt.Sprintf("> %v: Formsearch: success > query: %v", _r.Method, strqry), def.DEF_logdebg)
				}
			}
		}
	}
	if strcnt > 0 {
		strqry = "(" + strings.TrimSpace(strqry) + ")"
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): > Formsearch: success > Query(%v): %v",
			_r.Method, "getFormparams", strcnt, tol.JsonEscape(string(strqry))), def.DEF_loginfo)
	}
	//
	for key, values := range _r.Form { // range over map
		kix := tol.GetstringBetween(key, "[", "]")
		if len(kix) > 0 { // nur map[] beachten
			i, err := strconv.Atoi(kix)
			if err == nil { // nur numerische werte beachten > map[]
				for _, value := range values { // range over []string
					// log.Println("(", _r.Method, ") > Formparams: success > key[", i, "]: ", key, value)
					kst := strings.Replace(key, "[", ";", -1)
					kst = strings.Replace(kst, "]", "", -1)
					keyslice := strings.Split(kst, ";")
					var p tol.ColMap = make(tol.ColMap, 0)
					var sval = value
					if sval == "*" {
						if strcnt > 0 {
							fvp.FP_qery = strqry
							sval = strings.Replace(sval, "*", strqry, -1)
						}
					}
					p[keyslice[len(keyslice)-1]] = sval
					params[i] = p
				}
			}
		}
	}
	fvp.FP_parm = params
	if len(fvp.FP_parm) > 0 {
		// log.Println("(", _r.Method, ") > Formparams: success > Map: ", _fvp.FP_parm)
	}
	//
	return *fvp
}

func readFile(_fvp tol.TFVParams) (string, error) {
	//
	sname := "wwwgo/module/" + _fvp.FP_modl
	if _fvp.FP_suff != "" {
		sname = sname + "_" + _fvp.FP_suff
	}
	sname = sname + _fvp.FP_extn
	//
	file, err := os.Open(sname)
	defer file.Close()
	if err == nil {
		data, err := ioutil.ReadAll(file)
		if err == nil {
			return string(data), nil
		}
	}
	//
	return "", err
}

func readFilejson(_fvp tol.TFVParams, _r *http.Request) ([]byte, error) {
	var html string
	var err error = nil
	if _fvp.FP_suff != "" {
		switch _fvp.FP_suff {
		case "login":
			html = string(tol.CreateLogin(_r))
			log.Println("readFilejson(login):", html)
		default:
			html, err = readFile(_fvp)
		}
		html = strings.ReplaceAll(html, "%project%", fmt.Sprintf("_%v_", _fvp.FP_modl))
		html = tol.JsonEscape(string(html))
	} else {
		html = "Fehlender Suffix: " + _fvp.FP_suff
	}
	html = `{"success":true,"suid":"` + _fvp.FP_suid + `","html":"` + html + `"}`
	//
	return []byte(html), err
}

func getHome(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	_fvp.FP_what = "project"
	var fieldlist []string = make([]string, 0)
	var resultlist tol.ColMap
	fieldlist = append(fieldlist, def.DEF_fieldlayout)
	fieldlist = append(fieldlist, def.DEF_fieldproject)
	fieldlist = append(fieldlist, def.DEF_fieldsource)
	fieldlist = append(fieldlist, def.DEF_fieldapikey)
	fieldlist = append(fieldlist, def.DEF_fieldalias)
	fieldlist = append(fieldlist, def.DEF_fieldsiteurl)
	fieldlist = append(fieldlist, def.DEF_fieldidletime)
	fieldlist = append(fieldlist, def.DEF_fieldrouteurl)
	resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqllayout, fieldlist)
	var project string = def.DEF_project
	var source string = ""
	var html string = ""
	if err != nil {
		_fvp.FP_modl = "index_layout"
		_fvp.FP_extn = ".txt"
		html, err = readFile(_fvp)
		if err != nil {
			def.LogError("getHome("+_fvp.FP_modl+_fvp.FP_extn+")", err)
		}
	} else {
		project = resultlist[def.DEF_fieldproject]
		source = resultlist[def.DEF_fieldsource]
		html = resultlist[def.DEF_fieldlayout]
		var siteurl string = resultlist[def.DEF_fieldsiteurl]
		if len(siteurl) > 0 {
			def.DEF_siteurl = siteurl
		}
		idletime, err := strconv.ParseFloat(resultlist[def.DEF_fieldidletime], 64)
		if err != nil {
			def.LogError("getHome(parsefloat)", err)
			idletime = 1800
		}
		if idletime > 0 {
			def.DEF_idletime = idletime
		}
		var routeurl string = resultlist[def.DEF_fieldrouteurl]
		if len(routeurl) > 0 {
			def.DEF_routeurl = routeurl
		}
	}
	tol.Source = source
	html = strings.ReplaceAll(html, "%project%", fmt.Sprintf("%s", project))
	html = replaceAny(_r, _fvp, html, "script")
	//
	return _w.Write([]byte(html))
}

func receiveAjax(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) {
	if _r.Method == "POST" {
		s := "<h2>" + _fvp.FP_func + ":" + _fvp.FP_what + " was successfull.<h2>"
		_w.Write([]byte(s))
	}
}

// ##################################################
// fehlerbehandlung für webseite
func unknownParam(_w http.ResponseWriter, _fvp tol.TFVParams, _str string, _param string) []byte {
	sUnknownFrom := "> Function: '%s'<br>> What: '%s'<br>> Who: '%s'<br>>  From: '%s'<br>> Info: '%s'<br><br>There is no '%s' or '%s'"
	smsg := fmt.Sprintf(sUnknownFrom, _fvp.FP_func, _fvp.FP_what, _fvp.FP_who, _fvp.FP_from, _fvp.FP_info, _param, _str)
	msg := def.GetErrorByString(smsg, "alert", "> unknown"+_param+"()") + ","
	msg = `{"success":false,"suid":"` + _fvp.FP_suid + `",` + msg + `"html":""}`
	//
	return []byte(msg)
}

// ##################################################
func replaceSvg(_html string) string {
	var html string = _html
	var index int = strings.Index(html, `<%"`)
	for index > -1 {
		betw := tol.GetstringBetween(html, `<%"`, `;"%>`)
		beta := strings.Split(betw, ";")
		// svg-parameter vorbereiten
		var fvp tol.TFVParams
		fvp.FP_who = beta[0]  // svg-name
		fvp.FP_matx = beta[1] // svg-transfor.matrix
		fvp.FP_widt = beta[2] // svg-breite
		fvp.FP_heit = beta[3] // svg-höhe
		fvp.FP_view = beta[4] // svg-viewbox
		fvp.FP_shad = "true"  // svg-schatten
		// log.Println(" >>> SVG: @", index, betw, beta, fvp)
		jsvgarr, err := svg.SVG_getsvg_single(fvp)
		var jsvg gjs.Result = gjs.Get(`{"data":""}`, "data")
		jsvg.Str = fvp.FP_who
		if err == nil {
			if len(jsvgarr) > 1 {
				jsvg = gjs.Get(jsvgarr, fvp.FP_who)
			}
		}
		// log.Println(" >>> SVG: > result: ", len(jsvgarr), jsvg)
		html = strings.Replace(html, `<%"`+betw+`;"%>`, jsvg.String(), -1)
		index = strings.Index(html, `<%"`)
	}
	//
	return html
}

func replaceAny(_r *http.Request, _fvp tol.TFVParams, _html, _what string) string {
	// return _html
	//
	var fvp tol.TFVParams = _fvp
	var html string = _html
	var index int = strings.Index(html, `<%"`+_what+`;"%>`)
	for index > -1 {
		betw := tol.GetstringBetween(html, `<%"`, `;"%>`)
		if betw == _what {
			fvp.FP_what = _what
			var fieldlist []string = make([]string, 0)
			fieldlist = append(fieldlist, def.DEF_fieldcontent)
			resultlist, err := getTemplate(_r.Method, fvp, def.DEF_sqlcontent, fieldlist)
			if err != nil {
				def.LogError("replaceAny(template)", err)
				html = strings.Replace(html, `<%"`+betw+`;"%>`, "", -1)
			} else {
				html = strings.Replace(html, `<%"`+betw+`;"%>`, resultlist[def.DEF_fieldcontent], -1)
			}
		} else {
			break
		}
		index = strings.Index(html, `<%"`+_what+`;"%>`)
	}
	//
	return html
}

func getHtml(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	if _r.Method == "POST" { // POST zulassen
		// standard-rückgabe
		htby := []byte(`{"success":false,"suid":"` + _fvp.FP_suid + `"}`)
		if _fvp.FP_modl != "" {
			def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v",
				_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_loginfo)
			switch strings.Contains(tol.Source, _fvp.FP_what+";") {
			case true:
				msg := ""
				switch _fvp.FP_type {
				case "html":
					{ // html
						switch _fvp.FP_from {
						case "file": //..aus datei
							html, err := readFile(_fvp)
							html = replaceSvg(html)
							if err != nil {
								def.LogError("getHtml(file)", err)
								msg = def.GetErrorByString(fmt.Sprintf("%v", err), "alert", "> getHtml(html)") + ","
							}
							htby = []byte(`{"success":true,"suid":"` + _fvp.FP_suid + `",` + msg + `"html":"` + tol.JsonEscape(string(html)) + `"}`)
						case "db":
							{ //..aus db
								var fieldlist []string = make([]string, 0)
								var resultlist tol.ColMap
								fieldlist = append(fieldlist, def.DEF_fieldcontent)
								fieldlist = append(fieldlist, def.DEF_fieldproject)
								fieldlist = append(fieldlist, def.DEF_fieldsource)
								var project string = def.DEF_project
								var alias string = def.DEF_alias
								var html string = ""
								resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
								if err != nil {
									def.LogError("getHtml(db)", err)
									html = def.GetError(err, "alert", "getHtml(db)")
									htby = []byte(html)
								} else {
									project = resultlist[def.DEF_fieldproject]
									html = resultlist[def.DEF_fieldcontent]
									html = strings.ReplaceAll(html, "%project%", fmt.Sprintf("%s", project))
									html = strings.ReplaceAll(html, "%alias%", fmt.Sprintf("%s - ", alias))
									html = replaceAny(_r, _fvp, html, "script")
									html = replaceSvg(html)
									switch _fvp.FP_suff {
									case "login":
										html = string(tol.CreateLogin(_r))
										html = replaceSvg(html)
										log.Println("(", _r.Method, ") > login - Html1:", html)
										html = tol.JsonEscape(html)
										log.Println("(", _r.Method, ") > login - Html2:", html)
										htby = []byte([]byte(`{"success":true,"suid":"` + _fvp.FP_suid + `","html":"` + html + `"}`))
									default:
										if err != nil {
											msg = def.GetErrorByString(fmt.Sprintf("%v", err), "alert", "getHtml(db)") + ","
										}
										htby = []byte(`{"success":true,"suid":"` + _fvp.FP_suid + `",` + msg + `"html":"` + tol.JsonEscape(string(html)) + `"}`)
									}
								}
							}
						default:
							htby = []byte(unknownParam(_w, _fvp, "unknown", "from"))
							def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown from: ?",
								_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_logwarn)
						}
					}
				case "json":
					{ // json
						switch _fvp.FP_from {
						case "db":
							var fieldlist []string = make([]string, 0)
							var resultlist tol.ColMap
							var project string = def.DEF_project
							var html = ""
							fieldlist = append(fieldlist, def.DEF_fieldcontent)
							fieldlist = append(fieldlist, def.DEF_fieldproject)
							fieldlist = append(fieldlist, def.DEF_fieldsource)
							resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
							if err != nil {
								def.LogError("getHtml(json.db)", err)
								msg = def.GetErrorByString(fmt.Sprintf("%v", err), "alert", "> getTemplate(json.db)") + ","
							} else {
								html = resultlist[def.DEF_fieldcontent]
								project = resultlist[def.DEF_fieldproject]
							}
							html = strings.ReplaceAll(html, "%project%", fmt.Sprintf(`"%s"`, project))
							html = replaceSvg(html)
							switch _fvp.FP_suff {
							case "login":
								// log.Println("(", _r.Method, ") > login - html:", html)
								html = tol.JsonEscape(html)
								// log.Println("(", _r.Method, ") > login - html2:", html)
							case "search":
								// log.Println("(", _r.Method, ") > search - form:", _fvp.FP_parm)
								html, err = god.ImportMetaFields(_dvp, _fvp, html)
								// log.Println("(", _r.Method, ") > search - html2:", html)
								html = strings.Replace(html, "%data%", ",data:[]", -1)
								html = strings.Replace(html, "%mousedown%", `onmousedown="return false"`, -1)
								html = tol.JsonEscape(html)
							}
							htby = []byte(`{"success":true,"suid":"` + _fvp.FP_suid + `",` + msg + `"project":"` + project + `","html":"` + html + `"}`)
						default:
							htby = []byte(unknownParam(_w, _fvp, "unknown", "from"))
							def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown from: ?",
								_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_logwarn)
						}
					}
				default:
					htby = []byte(unknownParam(_w, _fvp, "unknown", "type"))
					def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown type: ?",
						_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_logwarn)
				}
			default:
				htby = []byte(unknownParam(_w, _fvp, "unknown", "what"))
				def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown modul: ?",
					_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_logwarn)
			}
			return _w.Write(htby)
		} else {
			def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown what: ?",
				_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from), def.DEF_logwarn)
		}
	}
	return 0, errors.New(fmt.Sprintf("( ERROR ) > Wrong method found ( %v ) in %s.", _r.Method, "getHtml()"))
}

func getThemes() string {
	var json string = `{`
	json = json + `"valueField": "label",`
	json = json + `"textField": "value",`
	json = json + `"data":[`
	json = json + `{"value":"default", "text":"Default", "selected":true},`
	json = json + `{"value":"black", "text":"Black"},`
	json = json + `{"value":"orange", "text":"Orange"},`
	json = json + `{"value":"green", "text":"Green"},`
	json = json + `{"value":"gray", "text":"Gray"}`
	json = json + `]}`
	//
	return json
}

func getValues(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	if _r.Method == "POST" {
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > who: %v > sid: %v",
			_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from, _fvp.FP_who, _fvp.FP_suid), def.DEF_loginfo)
		// standard-rückgabe
		htby := []byte(`{"success":false,"suid":"` + _fvp.FP_suid + `"}`)
		switch strings.Contains(tol.Source, _fvp.FP_what+";") {
		case true:
			{
				var project string = def.DEF_project
				switch _fvp.FP_what {
				case "menu":
					switch _fvp.FP_from {
					case "db":
						var fieldlist []string = make([]string, 0)
						var resultlist tol.ColMap
						var html string = ""
						fieldlist = append(fieldlist, def.DEF_fieldcontent)
						fieldlist = append(fieldlist, def.DEF_fieldproject)
						resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
						if err != nil {
							def.LogError("getValues(menu.db)", err)
							html = def.GetError(err, "alert", "getTemplate(menu.db)")
						} else {
							project = resultlist[def.DEF_fieldproject]
							html = strings.ReplaceAll(html, "%project%", fmt.Sprintf(`"%s"`, project))
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					case "dataverse":
						var html string = ""
						var err error = errors.New("getValues(menu.dataverse)")
						// root-dataverse
						rootname, err := god.GetDataverseName(_dvp, def.DEF_alias)
						if err != nil {
							def.LogError("getValues(menu.dataverse.1)", err)
							html = def.GetError(err, "alert", "getValues(dataverse."+def.DEF_alias+".menu)")
							//html = def.GetError(errors.New("Error while creating json for 'dataverse.menu'."), "alert")
						} else {
							// start - dataverse iteration
							log.Println("GetMenuFromDataverse(start)")
							html, err = god.GetMenuFromDataverse(_dvp, _fvp, def.DEF_alias, "", 10, true)
							if err != nil {
								def.LogError("getValues(menu.dataverse.2)", err)
								html = def.GetError(err, "alert", "getValues(dataverse."+def.DEF_alias+".menu)")
							} else {
								if len(html) == 0 {
									log.Println("\t . GetMenuFromDataverse(html):", html)
								}
								var sdjson string = ``
								//log.Printf("GetMenuFromDataverse(%v) > menu-set: %v, %v\n", aliasdv, sdatasets, err)
								if err == nil {
									sdatasets, err := god.GetDatasetsFromAlias(_dvp, _fvp, def.DEF_alias)
									if err == nil {
										sdjson, _ = god.GetMenuFromDatasets(sdatasets, def.DEF_alias, 10)
										if len(sdjson) > 0 {
											html = html + "," + sdjson
										}
									}
								}
								html = strings.Replace(def.MenuRoot(def.DEF_alias, rootname), "%children%", "["+html+"]", -1)
								html = strings.Replace(html, "%datasetPid%", _dvp.DP_datasetPid, -1)
								log.Println("GetMenuFromDataverse(done)")
								// log.Println("GetMenuFromDataverse(done):", html)
							}
						}
						htby = []byte(strings.ReplaceAll(html, `&#34;`, `"`))
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "menu.from"))
					}
				case "datagrid":
					switch _fvp.FP_from {
					case "db":
						var fieldlist []string = make([]string, 0)
						var html string = ""
						fieldlist = append(fieldlist, def.DEF_fieldcontent)
						fieldlist = append(fieldlist, def.DEF_fieldproject)
						fieldlist = append(fieldlist, def.DEF_fieldsource)
						resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
						if err != nil {
							def.LogError("getValues(datagrid.db)", err)
							html = def.GetError(err, "alert", "getValues(datagrid.db)")
						} else {
							project = resultlist[def.DEF_fieldproject]
							html = resultlist[def.DEF_fieldcontent]
							html = strings.ReplaceAll(html, "%project%", fmt.Sprintf(`"%s"`, project))
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					case "dataverse":
						html := ""
						// validity, superuser, id, err := god.CheckUserValidity(_dvp)
						// if validity {
						var err error = errors.New("( ERROR ) > Wrong 'kind' found.")
						switch _fvp.FP_who {
						case "user":
							// nothing to do..
							err = nil
							html = `{"success":false,"suid":"` + _fvp.FP_suid + `", "html":""}`
						case "dataverse": // dataverse - grid
							html, err = god.GetGridFromDataverse(_dvp, _fvp, true)
							if err != nil {
								def.LogError("getValues(datagrid.dataverse)", err)
							}
						case "dataset": // dataverse - grid
							html, err = god.GetGridFromDataset(_dvp, _fvp, true, "files;", "")
							if err != nil {
								def.LogError("getValues(datagrid.dataset)", err)
							}
						default:
							err = nil
							htby = []byte(unknownParam(_w, _fvp, "unknown", "datagrid."+_fvp.FP_who+""))
						}
						if err != nil {
							html = god.GetErrorByDataverse(_dvp, err, "alert", "getValues(datagrid.dataverse."+_fvp.FP_who+")")
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "datagrid.from"))
					}
				case "propgrid":
					switch _fvp.FP_from {
					case "db":
						var fieldlist []string = make([]string, 0)
						var html string = ""
						fieldlist = append(fieldlist, def.DEF_fieldcontent)
						fieldlist = append(fieldlist, def.DEF_fieldproject)
						fieldlist = append(fieldlist, def.DEF_fieldsource)
						resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
						if err != nil {
							if err != nil {
								def.LogError("getValues(propgrid.db)", err)
							}
							html = def.GetError(err, "alert", "getValues(propgrid.db)")
						} else {
							project = resultlist[def.DEF_fieldproject]
							html = resultlist[def.DEF_fieldcontent]
							html = strings.ReplaceAll(html, "%project%", fmt.Sprintf(`"%s"`, project))
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					case "dataverse":
						html := ""
						err := errors.New("( ERROR ) > Wrong 'kind' found.")
						switch _fvp.FP_who {
						case "file": // dataverse - property-grid
							html, err = god.GetPropGridFromDatasetFiles(_dvp, _fvp, "files")
						default:
							err = nil
							htby = []byte(unknownParam(_w, _fvp, "unknown", "propgrid."+_fvp.FP_who+""))
						}
						if err != nil {
							def.LogError("getValues(propgrid.dataverse)", err)
							html = god.GetErrorByDataverse(_dvp, err, "alert", "getValues(propgrid.dataverse."+_fvp.FP_who+")")
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					case "search":
						html, err := god.GetSearchResult(_dvp, _fvp)
						if err != nil {
							def.LogError("getValues(propgrid.search)", err)
							html = def.GetError(err, "alert", "getValues(propgrid.search)")
						} else {
							html = (`{"success":true,"suid":"` + _fvp.FP_suid + `","query":"` +
								tol.JsonEscape(string(_fvp.FP_qery)) + `","search":` + html + `}`)
						}
						html = strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`)
						// fmt.Printf("GetSearchResult(result): (%v) %v, %v\n", len(html), html, err)
						htby = []byte(html)
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "propgrid.from"))
					}
				case "event":
					switch _fvp.FP_from {
					case "db":
						var fieldlist []string = make([]string, 0)
						var html string = ""
						fieldlist = append(fieldlist, def.DEF_fieldcontent)
						fieldlist = append(fieldlist, def.DEF_fieldproject)
						fieldlist = append(fieldlist, def.DEF_fieldsource)
						resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlcontent, fieldlist)
						if err != nil {
							def.LogError("getValues(event.db)", err)
							html = def.GetError(err, "alert", "getValues(event.db)")
						} else {
							project = resultlist[def.DEF_fieldproject]
							html = resultlist[def.DEF_fieldcontent]
							html = strings.ReplaceAll(html, "%project%", fmt.Sprintf(`"%s"`, project))
						}
						htby = []byte(strings.ReplaceAll(replaceSvg(html), `&#34;`, `"`))
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "event.from"))
					}
				default:
					htby = []byte(unknownParam(_w, _fvp, "unknown", "event.what"))
				}
			}
		default:
			log.Println(" >>> getValues(): ", _fvp)
			htby = []byte(unknownParam(_w, _fvp, "empty", "table.what: "+_fvp.FP_what))
		}
		return _w.Write([]byte(htby))
	}
	return 0, errors.New(fmt.Sprintf("Wrong method found ( %v ) in %s.", _r.Method, "getValues()"))
}

func getParams(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	if _r.Method == "POST" {
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > who: %v > sid: %v",
			_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from, _fvp.FP_who, _fvp.FP_suid), def.DEF_loginfo)
		// standard-rückgabe
		htby := []byte(`{"success":false,"suid":"` + _fvp.FP_suid + `"}`)
		switch strings.Contains(tol.Source, _fvp.FP_what+";") {
		case true:
			{
				switch _fvp.FP_what {
				case "project":
					switch _fvp.FP_from {
					case "db":
						var html string = ""
						var fieldlist []string = make([]string, 0)
						var resultlist tol.ColMap
						fieldlist = append(fieldlist, def.DEF_fieldproject)
						fieldlist = append(fieldlist, def.DEF_fieldsource)
						fieldlist = append(fieldlist, def.DEF_fieldsiteurl)
						fieldlist = append(fieldlist, def.DEF_fieldrouteurl)
						fieldlist = append(fieldlist, def.DEF_fieldalias)
						fieldlist = append(fieldlist, def.DEF_fieldapikey)
						fieldlist = append(fieldlist, def.DEF_fieldidletime)
						resultlist, err := getTemplate(_r.Method, _fvp, def.DEF_sqlproject, fieldlist)
						if err != nil {
							def.LogError("getParams(project.db)", err)
							html = def.GetError(err, "alert", "getParams(project.db)")
						} else {
							var project string = resultlist[def.DEF_fieldproject]
							var source string = resultlist[def.DEF_fieldsource]
							var siteurl string = resultlist[def.DEF_fieldsiteurl]
							var alias string = resultlist[def.DEF_fieldalias]
							var apikey string = resultlist[def.DEF_fieldapikey]
							var routeurl string = resultlist[def.DEF_fieldrouteurl]
							if len(siteurl) > 0 {
								def.DEF_siteurl = siteurl
							}
							if len(apikey) > 0 {
								def.DEF_apikey = apikey
							}
							if len(alias) > 0 {
								def.DEF_alias = alias
							}
							idletime, err := strconv.ParseFloat(resultlist[def.DEF_fieldidletime], 64)
							if err != nil {
								def.LogError("getParams(project.db.parsefloat)", err)
								idletime = 1800
							}
							if idletime > 0 {
								def.DEF_idletime = idletime
							}
							if len(routeurl) > 0 {
								def.DEF_routeurl = routeurl
							}
							def.LogMessage("", fmt.Sprintf("( %v ) > %v(): fields: %v, result: %v",
								_r.Method, _fvp.FP_func, fieldlist, resultlist), def.DEF_loginfo)
							var ipmap = strings.Split(tol.GetIP(_r), ":")
							def.LogMessage("", fmt.Sprintf("( %v ) > %v(): ip: %v",
								_r.Method, _fvp.FP_func, ipmap), def.DEF_loginfo)
							html = `{` +
								`"success":true` +
								`,"suid":"` + _fvp.FP_suid +
								`","project":"` + project +
								`","source":"` + source +
								`","alias":"` + alias +
								`","apikey":"` + apikey +
								`","idletime":"` + fmt.Sprintf("%f1.0", idletime)
							if len(ipmap) == 2 {
								html += `","localip":"` + ipmap[0]
								html += `","localport":"` + ipmap[1]
							} else {
								html += `","localip":"Can not resolve client ip`
							}
							html += `"}`
						}
						htby = []byte(html)
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "project.from."+_fvp.FP_from+""))
					}
				case "params":
					var html string = ""
					// var err error
					switch _fvp.FP_from {
					case "db":
						switch _fvp.FP_who {
						case "get.themes":
							html = getThemes()
							html = `{"success":true, "suid":"` + _fvp.FP_suid +
								`", "themes":` + html + `}`
						case "search.file":
							html = (`{"success":false, "suid":"` + _fvp.FP_suid + `"}`)
						case "search.load":
							html = (`{"success":false, "suid":"` + _fvp.FP_suid + `"}`)
						case "search.save":
							html = (`{"success":false, "suid":"` + _fvp.FP_suid + `"}`)
						case "search.header":
							// html, err =
							var columns tol.JsnColMap = make(tol.JsnColMap, 0)
							data, err := json.Marshal(tol.DataColList)
							if err == nil {
								var sdata string = strings.ReplaceAll(string(data), `\"`, ``)
								// log.Printf("GetSearchResult(data): %v\n", sdata)
								columns["dataset"] = sdata
								file, err := json.Marshal(tol.FileColList)
								if err == nil {
									var sfile string = strings.ReplaceAll(string(file), `\"`, ``)
									// log.Printf("GetSearchResult(file): %v\n", sfile)
									columns["file"] = sfile
								}
							}
							// log.Printf("GetSearchResult(cols): %v\n", columns)
							cols, err := json.Marshal(columns)
							var scols string = strings.ReplaceAll(string(cols), `\"`, `"`)
							scols = strings.ReplaceAll(scols, `"{`, `{`)
							scols = strings.ReplaceAll(scols, `}"`, `}`)
							def.LogMessage("", fmt.Sprintf("GetSearchResult(%v) > cols: %v", "all", string(cols)), def.DEF_logdebg)
							html = `{"success":true, "suid":"` + _fvp.FP_suid +
								`", "columns":` + scols + `}`
						default:
							html = string(unknownParam(_w, _fvp, "unknown", "params.who."+_fvp.FP_who+""))
						}
					default:
						html = string(unknownParam(_w, _fvp, "unknown", "params.from."+_fvp.FP_from+""))
					}
					htby = []byte(html)
				case "svg":
					switch _fvp.FP_from {
					case "modul":
						svg.SVG_object.Class = "app-tb-btn-svg"
						svg.SVG_object.Width = 30
						svg.SVG_object.Height = 30
						svg.SVG_object.Trans = "matrix(1,0,0,1,0,0)"
						svg.SVG_object.Anima = ""
						svg.SVG_object = svg.SVG_gethtml_all(svg.SVGViewbox)
						htby = []byte((`{"success":true,"total":` + svg.SVG_object.Total + `,"suid":"` + _fvp.FP_suid + `","svgobject":` + string(svg.SVG_object.Object) + `}`))
					default:
						htby = []byte(unknownParam(_w, _fvp, "unknown", "svg.from"))
					}
				case "getsvg":
					switch _fvp.FP_from {
					case "modul":
						// log.Println(" >>> getsvg: ", _fvp.FP_who)
						html, err := svg.GetSVG_ByParams(_fvp)
						if err != nil {
							def.LogError("getParams(getsvg.modul)", err)
							html = def.GetError(err, "alert", "getTemplate(getsvg.modul)")
						}
						htby = []byte(html)
					}
				default:
					htby = []byte(unknownParam(_w, _fvp, "unknown", "event.what"))
				}
			}
		default:
			log.Println(" >>> getParams(): ", _fvp)
			htby = []byte(unknownParam(_w, _fvp, "empty", "table.what: "+_fvp.FP_what))
		}
		return _w.Write([]byte(htby))
	}
	return 0, errors.New(fmt.Sprintf("Wrong method found ( %v ) in %s.", _r.Method, "getParams()"))
}

// #############################################################################
// ### redirect url and destroy session
// #############################################################################
func routeToURL(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) {
	if _r.Method == "POST" {
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > who: %v > sid: %v",
			_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from, _fvp.FP_who, _fvp.FP_suid), def.DEF_loginfo)
		//
		if len(_fvp.FP_suid) > 63 {
			delete(tol.Ue, _fvp.FP_suid)
			def.LogMessage2Level("", fmt.Sprintf("( %v ) > Multiplexer(): Session( %v ) session is finally terminated.",
				_r.Method, _fvp.FP_suid), def.DEF_loginfo)
		}
		// standard-rückgabe
		htby := []byte(`{"success":true,"suid":"` + _fvp.FP_suid + `","route":"` + tol.GetRouteUrl(_dvp) + `"}`)
		_w.Write([]byte(htby))
		//
	}
}

// #############################################################################
// ### handler for get-request
// #############################################################################
func handlerGet(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	// log.Printf("\n( %v ) > request: %v\n", _r.Method, _fvp)
	if _fvp.FP_func != "" {
		var i int = 0
		var err error = nil
		switch _fvp.FP_func {
		case "getHome": // geht lt. jquery wegen synchronem request nicht
			i, err = getHome(_w, _r, _fvp, _dvp) // anschlessend ist die seite blockiert
		case "getValues":
			return getValues(_w, _r, _fvp, _dvp)
		case "getParams":
			// log.Printf("\n( %v ) > result: %v\n", _r.Method, _dvp)
			i, err = getParams(_w, _r, _fvp, _dvp)
		case "receiveAjax":
			receiveAjax(_w, _r, _fvp, _dvp)
		default:
			html := unknownParam(_w, _fvp, "unknown", "function")
			def.LogError("", errors.New(fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown function: ?",
				_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from)))
			i, err = _w.Write([]byte(html))
		}
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > who: %v was written!",
			_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from, _fvp.FP_who), def.DEF_loginfo)
		//
		return i, err
	} else {
		i, err := getHome(_w, _r, _fvp, _dvp)
		if err != nil {
			def.LogError("handlerGet(getHome)", err)
			_, err := _w.Write([]byte(def.GetError(err, "alert", "getHome()")))
			if err != nil {
				// alles zu spät
			}
		}
		def.LogMessage("", fmt.Sprintf("( %v ) > getHome(): %v bytes written!",
			_r.Method, i), def.DEF_loginfo)
		//
		return i, err
	}
	//
	return 0, errors.New(fmt.Sprintf("( ERROR ) > Wrong function found ( %v ) in %s.", _fvp.FP_func, "handlerGet()"))
}

// #############################################################################
// ### handler for post-request
// #############################################################################
func handlerPost(_w http.ResponseWriter, _r *http.Request, _fvp tol.TFVParams, _dvp tol.TDVParams) (int, error) {
	// log.Printf("\n( %v ) > request: %v\n", _r.Method, _fvp)
	var i int = 0
	var err error = nil
	if _fvp.FP_func != "" {
		//
		switch _fvp.FP_func {
		case "getHtml":
			i, err = getHtml(_w, _r, _fvp, _dvp)
		case "getValues":
			i, err = getValues(_w, _r, _fvp, _dvp)
		case "getParams":
			i, err = getParams(_w, _r, _fvp, _dvp)
		case "routeToURL":
			routeToURL(_w, _r, _fvp, _dvp)
		case "receiveAjax":
			receiveAjax(_w, _r, _fvp, _dvp)
		default:
			html := unknownParam(_w, _fvp, "unknown", "function")
			def.LogError("", errors.New(fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > unknown function: ?",
				_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from)))
			i, err = _w.Write([]byte(html))
			//
		}
		def.LogMessage("", fmt.Sprintf("( %v ) > %v(): what: %v > modul: %v > type: %v > from: %v > who: %v was written!",
			_r.Method, _fvp.FP_func, _fvp.FP_what, _fvp.FP_modl, _fvp.FP_type, _fvp.FP_from, _fvp.FP_who), def.DEF_loginfo)
	} else {
		i = 0
		err = errors.New(fmt.Sprintf("( ERROR ) > Wrong function found ( %v ) in %s.", _fvp.FP_func, "getHtml()"))
	}
	//
	return i, err
}

// #############################################################################
// ### read all get/post and form-parameter
// #############################################################################
func getparamlist(_w http.ResponseWriter, _r *http.Request) string {
	_dvp := getDataParams(_r)
	_fvp := getFormparams(_r)
	//
	var ue tol.TUserEntry
	var uechange bool = false
	if len(_fvp.FP_suid) > 0 {
		if tol.Ue == nil {
			tol.Ue = make(tol.TUserEntries, 0)
		}
		var ok bool = false
		ue, ok = tol.Ue[_fvp.FP_suid]
		if ok {
			def.LogMessage("", fmt.Sprintf("( %v ) > Multiplexer(): Idle since (%vs ), Session( %v )",
				_r.Method, time.Since(ue.UE_IdleTime).Seconds(), _fvp.FP_suid), def.DEF_logdebg)
			ue.UE_FVParams = _fvp
			ue.UE_DVParams = _dvp
			tol.Ue[_fvp.FP_suid] = ue
			if ue.UE_Done {
				def.LogMessage2Level("", fmt.Sprintf("( %v ) > Multiplexer(): Session( %v ) session becomes completed.",
					_r.Method, _fvp.FP_suid), def.DEF_loginfo)
				msg := def.GetErrorByString(
					_fvp.FP_func+`(`+_fvp.FP_info+`).<BR><BR><BR>Session  will be reloaded after this message.`, `alert`,
					`Completed at `+ue.UE_Released.Format(def.DEF_stampISO))
				var html string = `{"released":true,"suid":"` + _fvp.FP_suid + `",` + msg + `}`
				_w.Write([]byte(html))
				delete(tol.Ue, _fvp.FP_suid)
				//
				return _fvp.FP_suid
			} else {
				ue.UE_IdleTime = time.Now()
			}
		} else {
			def.LogMessage2Level("", fmt.Sprintf("( %v ) > Multiplexer(): Session was NOT found, will be (re)created ( %v )",
				_r.Method, _fvp.FP_suid), def.DEF_loginfo)
			ue.UE_Done = false
			ue.UE_FVParams = _fvp
			ue.UE_DVParams = _dvp
			ue.UE_IdleTime = time.Now()
			var ipmap = strings.Split(tol.GetIP(_r), ":")
			if len(ipmap) == 2 {
				ue.UE_IpAddress = ipmap[0]
				ue.UE_IpPort = ipmap[1]
			}
		}
		//
		uechange = (tol.Ue[_fvp.FP_suid].UE_DVParams != ue.UE_DVParams)
		if uechange {
			def.LogMessage("", fmt.Sprintf("( %v ) > Multiplexer(): UserEntry( %v ): %v",
				_r.Method, _fvp.FP_suid, ue.UE_DVParams), def.DEF_logdebg)
		}
		//
		tol.Ue[_fvp.FP_suid] = ue
	}
	//
	return _fvp.FP_suid
}

// #############################################################################
// ### handlefunc to process the inquiries
// #############################################################################
func multiplexer(_w http.ResponseWriter, _r *http.Request) {
	suid := getparamlist(_w, _r)
	ue := tol.Ue[suid]
	//log.Println("(", _r.Method, ") > Multiplexer():", suid, ue.UE_FVParams, ue.UE_DVParams)
	if ue.UE_Done == false {
		switch _r.Method {
		case "GET":
			handlerGet(_w, _r, ue.UE_FVParams, ue.UE_DVParams)
		case "POST":
			handlerPost(_w, _r, ue.UE_FVParams, ue.UE_DVParams)
		default:
			getHome(_w, _r, ue.UE_FVParams, ue.UE_DVParams)
		}
	} else {
		def.LogMessage2Level("", fmt.Sprintf("( %v ) > Multiplexer(): Session already terminated.",
			_r.Method), def.DEF_loginfo)
		// standard-rückgabe
		var html string = ""
		if _r.Method == "POST" {
			html = `{"success":false,"suid":""}`
		}
		_w.Write([]byte(html))
	}
}

// #############################################################################
// ### handlefunc for folders ( denying access )
// #############################################################################

func httpErr(_w http.ResponseWriter, _r *http.Request, _err string, _path string, _code int) string {
	serror := fmt.Sprintf("(%v) File or directory not found - %v", _code, _err)
	def.LogMessage2Level("", fmt.Sprintf("( %v ) > %v path: %v.", _r.Method, serror, _path), def.DEF_logwarn)
	//
	http.Error(_w, serror, _code)
	//
	return serror
}

func servefiles(_w http.ResponseWriter, _r *http.Request) {
	var path string = html.EscapeString(_r.URL.Path)
	// fmt.Println("servefiles(1):", filepath.Join("./", def.DEF_codebase))
	nfs := newFileSystem{http.Dir(filepath.Join("./", def.DEF_codebase))}
	//
	// bewertung, ob von ausserhalb aufgerufen
	if strings.Index(def.DEF_toolboxdirs, ";"+path+";") > -1 {
		_fvp := getFormparams(_r) // unter anderem die "SUID" ermitteln
		_, ok := tol.Ue[_fvp.FP_suid]
		if !ok && (_r.Method == "GET") {
			def.LogMessage2Level("", fmt.Sprintf(`( %v ) > external path: "%v" will be used as: "%v".`, _r.Method, path, "/"), def.DEF_loginfo)
		}
		path = "/" // neue basis
	}
	//
	serror := fmt.Sprintf("cannot open")
	if strings.Index(path, "/"+def.DEF_codebase) == -1 { //gar nicht erst versuchen
		f, err := nfs.fs.Open(path)
		// fmt.Println("servefiles(2):", path, "in", "/"+def.DEF_codebase, err)
		if err != nil {
			httpErr(_w, _r, serror, path, http.StatusNotFound)
		} else {
			defer f.Close()
			s, err := f.Stat()
			if err == nil {
				if s.IsDir() {
					switch path {
					case "/": // normale abarbeitung
						multiplexer(_w, _r)
						return
					default: // anforderung abweisen
						httpErr(_w, _r, serror, path, http.StatusNotFound)
					}
				} else { // angeforderte datei schreiben
					http.ServeContent(_w, _r, s.Name(), s.ModTime(), f)
					def.LogMessage2Level("", fmt.Sprintf("( %v ) > %v was written.", _r.Method, path), def.DEF_loginfo)
					return
				}
			}
		}
	} else { // anforderung abweisen
		httpErr(_w, _r, serror, path, http.StatusNotFound)
	}
}

func init() {
	log.Println("Initialize Package - Main..")
}

// #############################################################################
// ### try, catch, finally - interface
// #############################################################################
type Exception interface{}
type Block struct {
	InUse   bool
	Try     func()
	Catch   func(Exception)
	Finally func()
}

func (tcf Block) Do() {
	if tcf.Finally != nil {
		defer tcf.Finally()
	}
	if tcf.Catch != nil {
		defer func() {
			if r := recover(); r != nil {
				tcf.Catch(r)
			}
		}()
	}
	tcf.Try()
}

// #############################################################################
// ### check the session validity ( one time per second )
// #############################################################################
func checkcompletion() {
	var inuse bool = false
	for now := range time.Tick(time.Second) {
		Block{
			Try: func() {
				if inuse {
					panic("Oh sh.., already in use.")
				}
				inuse = true
				// log.Println("( RUN ) > Session running (", tol.Ue, ") at ", now.Format(def.DEF_stampISO), ")")
				for key, ue := range tol.Ue {
					//log.Println("( RUN ) > Session running (", ue.UE_IpAddress+":"+ue.UE_IpPort, ") at ", now.Format(def.DEF_stampISO), "> session:", key)
					if !ue.UE_Done {
						if time.Until(ue.UE_IdleTime).Seconds() < (def.DEF_idletime * -1) {
							ue.UE_Done = true
							ue.UE_Released = now
							//
							tol.Ue[key] = ue
							//
							log.Println("( DONE ) > Session is scheduled to end (", ue.UE_IpAddress+":"+ue.UE_IpPort, ") at ", now.Format(def.DEF_stampISO), "> session:", key)
						}
					}
				}
			},
			Catch: func(e Exception) {
				fmt.Printf("caught: %v\n", e)
			},
			Finally: func() {
				inuse = false
			},
		}.Do()
	}
}

func main() {
	def.GetArguments() //
	// validation check
	go checkcompletion()
	//
	httpmux := http.NewServeMux()
	httpmux.HandleFunc("/", servefiles)
	httpmux.HandleFunc(def.DEF_metrixdirs, goMetrix.Handler)
	httpmux.Handle(def.DEF_wasmdirs_www, http.StripPrefix(def.DEF_wasmdirs_www, func(next http.Handler) http.Handler { //Prevent indexing
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.URL.Path == "" {
				http.NotFound(w, r)
				return
			}
			next.ServeHTTP(w, r)
		})
	}(http.FileServer(http.Dir(def.DEF_wasmdirs_fs)))))

	/* DEBUG HILFE
	httpmux.Handle("/css/", http.StripPrefix("/css/", func(next http.Handler) http.Handler { //Prevent indexing
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.URL.Path == "" {
				http.NotFound(w, r)
				return
			}
			next.ServeHTTP(w, r)
		})
	}(http.FileServer(http.Dir("static/css/")))))

	httpmux.Handle("/images/", http.StripPrefix("/images/", func(next http.Handler) http.Handler { //Prevent indexing
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.URL.Path == "" {
				http.NotFound(w, r)
				return
			}
			next.ServeHTTP(w, r)
		})
	}(http.FileServer(http.Dir("static/images/")))))
	*/
	//
	log.Println("Initialize HTTP-Server @ " + fmt.Sprintf("%s:%v", def.DEF_httphost, def.DEF_httpport) + "..")
	http.ListenAndServe(fmt.Sprintf("%s%v", ":", def.DEF_httpport), httpmux)
}
