package funcmap

import (
	"fmt"
	"log"
	"reflect"
	"sort"
	"strings"
	"text/template"

	"github.com/gobwas/glob"
	"gogs.carduccidante.edu.it/karmen/core/orm"
)

var FuncMap template.FuncMap = template.FuncMap{
	"comma":        comma,
	"groupClasses": groupClasses,
	"abbrev":       abbrev,
	"nbsp":         nbsp,
	"globFilter":   globFilter,
	"toUpper":      toUpper,
	"order":        order,
	"stringSlice":  stringSlice,
}

func order(items []string) []string {
	sort.Strings(items)

	return items
}

func stringSlice(items interface{}) []string {
	var result []string

	switch reflect.TypeOf(items).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(items)
		for i := 0; i < s.Len(); i++ {
			result = append(result, fmt.Sprintf("%s", s.Index(i)))
		}
	default:
		log.Println("Unknown type")
	}

	return result
}

func toUpper(content string) string {
	return strings.ToUpper(content)
}

func globFilter(pattern, content string) bool {
	g := glob.MustCompile(pattern)

	return g.Match(content)
}

func comma(classes []*orm.Class) string {
	var names []string
	for _, c := range classes {
		names = append(names, c.Name)
	}
	return strings.Join(names, ",")
}

func abbrev(name string) string {
	var result string
	splits := strings.Split(name, " ")

	if len(splits) > 1 {
		for i := len(splits) - 1; i >= 0; i-- {
			if i == len(splits)-1 {
				result += splits[i] + " "
				continue
			}
			result += strings.ToUpper(string(splits[i][0]) + ".")
		}
	} else {
		result += strings.ToUpper(string(name[0]) + ".")
	}

	return result
}

func nbsp(num int, text string) string {
	return text + strings.Repeat("&nbsp;", num)
}

func groupClasses(classes []*orm.Class) string {
	var groups []string

	groupByAddresses := make(map[string][]string)
	addressesAbbrev := map[string]string{
		"Linguistico":       "LIN",
		"Classico":          "CLA",
		"Musicale":          "M",
		"Economico sociale": "ES",
		"Scienze umane":     "SU",
	}
	for _, c := range classes {
		groupByAddresses[c.Field] = append(groupByAddresses[c.Field], fmt.Sprintf("%d%s", c.Year, c.Section))
	}

	for address, classes := range groupByAddresses {
		var group string
		if len(classes) > 1 {
			group = fmt.Sprintf("[%s]%s", strings.Join(classes, ","), addressesAbbrev[address])
		} else {
			group = fmt.Sprintf("%s %s", strings.Join(classes, ","), addressesAbbrev[address])
		}
		groups = append(groups, group)
	}
	return strings.Join(groups, ",")
}
