package renderer

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"strings"
	"time"

	"gitlab.scity.coop/maas/navitia-golang/types"
)

func TimeFrom(d any) *time.Time {

	if date, ok := d.(time.Time); ok {
		return &date
	} else if date, ok := d.(string); ok {
		datetime, err := time.Parse("2006-01-02T15:04:05Z", date)
		if err != nil {
			panic(err)
		}
		return &datetime
	}
	return nil
}

func TimestampFrom(d any) *time.Time {

	if date, ok := d.(time.Time); ok {
		return &date
	} else if date, ok := d.(string); ok {
		datetime, err := time.Parse("2006-01-02T15:04:05Z", date)
		if err != nil {
			panic(err)
		}
		return &datetime
	}
	return nil
}

func TimeFormat(d any, f string) string {
	date := TimeFrom(d)
	if date == nil {
		return ""
	}
	if date.Before(time.Now().Add(-24 * 365 * 30 * time.Hour)) {
		return ""
	}
	return date.Format(f)
}

func GenderISO5218(d any) string {
	if date, ok := d.(string); ok {
		switch date {
		case "0":
			return "Inconnu"
		case "1":
			return "Masculin"
		case "2":
			return "Féminin"
		case "9":
			return "Sans objet"
		}
	}
	if date, ok := d.(int64); ok {
		switch date {
		case 0:
			return "Inconnu"
		case 1:
			return "Masculin"
		case 2:
			return "Féminin"
		case 9:
			return "Sans objet"
		}
	}
	return ""
}

func JSON(v any) template.JS {
	result, _ := json.Marshal(v)
	return template.JS(result)
}

func RawJSON(v any) string {
	buf := new(bytes.Buffer)
	enc := json.NewEncoder(buf)
	enc.SetEscapeHTML(false)
	err := enc.Encode(&v)
	if err != nil {
		return ""
	}
	return strings.TrimSuffix(buf.String(), "\n")

}

func UnescapeHTML(s string) template.HTML {
	return template.HTML(s)
}

func Dict(v ...interface{}) map[string]interface{} {
	dict := map[string]interface{}{}
	lenv := len(v)
	for i := 0; i < lenv; i += 2 {
		key := strval(v[i])
		if i+1 >= lenv {
			dict[key] = ""
			continue
		}
		dict[key] = v[i+1]
	}
	return dict
}

func WalkingLength(s types.Section) (l int) {
	l = 0
	if s.Mode == "walking" {
		for _, p := range s.Path {
			l = l + int(p.Length)
		}
	}
	return
}

func strval(v interface{}) string {
	switch v := v.(type) {
	case string:
		return v
	case []byte:
		return string(v)
	case error:
		return v.Error()
	case fmt.Stringer:
		return v.String()
	default:
		return fmt.Sprintf("%v", v)
	}
}

func Divide[V int | float64](a, b V) V {
	return a / b
}
