package utils

import (
	"encoding/json"
	"sort"
	"strings"
)

/* ---------------------------------------------------------------- *
 * METHODS: json
 * ---------------------------------------------------------------- */

func JsonToArrayOfStrings(s string, value *[]string) {
	var err error
	err = json.Unmarshal([]byte(s), &value)
	if err != nil {
		panic(err)
	}
}

/* ---------------------------------------------------------------- *
 * METHODS: conversion
 * ---------------------------------------------------------------- */

func BoolToInt(cond bool) int {
	if cond {
		return 1
	}
	return 0
}

/* ---------------------------------------------------------------- *
 * METHODS: for integer lists
 * ---------------------------------------------------------------- */

func Min2(x int, y int) int {
	if x <= y {
		return x
	}
	return y
}

func Max2(x int, y int) int {
	if x >= y {
		return x
	}
	return y
}

func MinList(x []int) int {
	if len(x) == 0 {
		panic("Cannot compute the maximum of an empty array.")
	}
	var val int = x[0]
	for i, val_ := range x {
		if i > 0 {
			val = Min2(val, val_)
		}
	}
	return val
}

func MaxList(x []int) int {
	if len(x) == 0 {
		panic("Cannot compute the maximum of an empty array.")
	}
	var val int = x[0]
	for i, val_ := range x {
		if i > 0 {
			val = Max2(val, val_)
		}
	}
	return val
}

func SumList(x []int) int {
	var val int = 0
	for _, val_ := range x {
		val += val_
	}
	return val
}

/* ---------------------------------------------------------------- *
 * METHODS: for string lists
 * ---------------------------------------------------------------- */

func CopyStringList(list []string) []string {
	var listCopy = make([]string, len(list))
	for i, value := range list {
		listCopy[i] = value
	}
	return listCopy
}

func StrListContains(list []string, x string) bool {
	for _, obj := range list {
		if obj == x {
			return true
		}
	}
	return false
}

func SortStrings(list *[]string) {
	sort.Slice(*list, func(i int, j int) bool {
		u := strings.ToLower((*list)[i])
		v := strings.ToLower((*list)[j])
		cmp := strings.Compare(u, v)
		return (cmp < 0)
	})
}

func FilterStrings(list *[]string, f func(string) bool) []string {
	var listFiltered = []string{}
	for _, val := range *list {
		if f(val) {
			listFiltered = append(listFiltered, val)
		}
	}
	return listFiltered
}

func UnionStrings2(list1 []string, list2 []string) []string {
	var mark = make(map[string]bool)
	for _, item := range list1 {
		mark[item] = true
	}
	for _, item := range list2 {
		mark[item] = true
	}
	var list = make([]string, len(mark))
	var i int = 0
	for item, _ := range mark {
		list[i] = item
		i++
	}
	return list
}

// assumes that listTo contains no duplicates
func UnionStringsInPlace(listTo *[]string, listFrom []string) {
	var mark = make(map[string]bool)
	for _, item := range listFrom {
		mark[item] = true
	}
	for _, item := range *listTo {
		mark[item] = false // signals suppression of duplicate addition
	}
	for item, isNew := range mark {
		if isNew {
			*listTo = append(*listTo, item)
		}
	}
}

func UnionStringsList(lists [][]string) []string {
	var list = []string{}
	for _, list_ := range lists {
		UnionStringsInPlace(&list, list_)
	}
	return list
}

/* ---------------------------------------------------------------- *
 * METHODS: for maps
 * ---------------------------------------------------------------- */

func CopyMapStringBool(m map[string]bool) map[string]bool {
	var mCopy = map[string]bool{}
	for key, value := range m {
		mCopy[key] = value
	}
	return mCopy
}
