package util

import (
	"fmt"
	"regexp"
	"sort"
	"strings"
)

type RouteModel struct {
	Label       int
	Host        string
	Path        string
	Namespace   string
	ServiceName string
	ServicePort int
	TestCases   []string
}

func (r RouteModel) NamespaceAndService() string {
	return fmt.Sprintf("%s/%s", r.Namespace, r.ServiceName)
}

func (r RouteModel) Match(testCase string) bool {
	if !strings.Contains(r.Path, "*") {
		return r.Path == testCase
	}
	regex, _ := regexp.Compile(fmt.Sprintf("^%s$", strings.Replace(r.Path, "*", "(.*)", -1)))
	return regex.Match([]byte(testCase))
}

type RouteModels []RouteModel

func (rs RouteModels) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
}

func (rs RouteModels) Less(i, j int) bool {
	return rs[i].NamespaceAndService() < rs[j].NamespaceAndService()
}

func (rs RouteModels) Len() int {
	return len(rs)
}

func (rs RouteModels) Match(testCase string) *RouteModel {
	for _, r := range rs {
		if r.Match(testCase) {
			return &r
		}
	}
	return nil
}

func (rs RouteModels) Validate() error {
	sort.Sort(rs)
	for _, r := range rs {
		for _, tc := range r.TestCases {
			bestMatch := rs.Match(tc)
			if bestMatch == nil {
				return fmt.Errorf("testcase %s can not match any path", tc)
			} else if bestMatch.Label != r.Label {
				return fmt.Errorf("testcase %s match failed: expected %s but got %s", tc, r.Path, bestMatch.Path)
			}
		}
	}
	return nil
}
