package helper

import (
	"path"
	"regexp"
	"strings"

	"gitbase.de/apairon/mark2web/config"
)

// NavElement is one element with ist attributes and subs
type NavElement struct {
	Navname string
	GoTo    string
	Active  bool

	Data interface{}

	This config.ThisPathConfig

	SubMap   *map[string]*NavElement
	SubSlice *[]*NavElement
}

// BuildNavigation builds the navigation trees for use in templates
func BuildNavigation(conf *config.PathConfigTree, curNavMap *map[string]*NavElement, curNavSlice *[]*NavElement, navActive *[]*NavElement, activeNav string) {
	for _, el := range conf.Sub {
		if el.Hidden {
			continue // ignore hidden nav points from collections
		}

		var ignNav *string
		if p := el.Config.Path; p != nil {
			ignNav = p.IgnoreForNav
		}
		if ignNav != nil && *ignNav != "" {
			regex, err := regexp.Compile(*ignNav)
			if err != nil {
				Log.Panicf("could not compile IngoreForNav regexp '%s' in '%s': %s", *ignNav, el.InputPath, err)
			}
			if regex.MatchString(path.Base(el.InputPath)) {
				Log.Debugf("ignoring input directory '%s' in navigation", el.InputPath)
				continue
			}
		}

		elPath := strings.TrimPrefix(el.OutputPath, config.Config.Directories.Output+"/")

		subMap := make(map[string]*NavElement)
		subSlice := make([]*NavElement, 0)
		navEl := NavElement{
			Active:   strings.HasPrefix(activeNav, elPath),
			Data:     el.Config.Data,
			SubMap:   &subMap,
			SubSlice: &subSlice,
		}

		navEl.This = el.Config.This

		if navEl.Active {
			// add to navActive level navigation
			currentLevel := strings.Count(activeNav, "/")
			if len(*navActive) <= currentLevel {
				// not registered
				*navActive = append(*navActive, &navEl)
			}
		}

		n := el.Config.This.Navname
		if n != nil {
			navEl.Navname = *n
		}
		g := el.Config.This.GoTo
		if g != nil {
			if strings.HasPrefix(*g, "/") {
				// abslute
				navEl.GoTo = *g
			} else {
				// relative
				navEl.GoTo = elPath + "/" + *g
			}
		} else {
			navEl.GoTo = elPath + "/"
		}

		if activeNav != "" && activeNav != "/" {
			// calculate relative path
			bToRoot := BackToRoot(activeNav)
			navEl.GoTo = bToRoot + navEl.GoTo
			navEl.GoTo = path.Clean(navEl.GoTo)
		}

		(*curNavMap)[navEl.Navname] = &navEl
		if curNavSlice != nil {
			*curNavSlice = append(*curNavSlice, &navEl)
		}

		BuildNavigation(el, &subMap, &subSlice, navActive, activeNav)
	}
}
