package main

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

// Copyright (C) 2022 Giuseppe Lavagetto <joe@wikimedia.org>
// Copyright (C) 2022 Wikimedia Foundation, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Sort query parameters, matching the sort in libvmod-querysort
// See <https://wikitech.wikimedia.org/wiki/Query_string_normalization>
func QuerySort(url string) (string, error) {
	if url == "" {
		return "", nil
	}

	base, rawQuery, found := strings.Cut(url, "?")
	if !found {
		return "", nil
	}
	// spot single-param queries
	if !strings.Contains(rawQuery, "&") {
		return "", nil
	}
	var queryTokens []string
	for _, param := range strings.Split(rawQuery, "&") {
		if param != "" {
			queryTokens = append(queryTokens, param)
		}
	}
	sort.SliceStable(queryTokens, func(i, j int) bool {
		k1, k2 := queryTokens[i], queryTokens[j]
		for _, stop := range []string{"=", "[", "%5B", "%5b"} {
			k1, _, _ = strings.Cut(k1, stop)
			k2, _, _ = strings.Cut(k2, stop)
		}
		return k1 < k2
	})
	return fmt.Sprintf("%s?%s", base, strings.Join(queryTokens, "&")), nil
}
