package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)

func stringsToInt(inputStrings []string) []int {
	integers := make([]int, len(inputStrings))
	for i, v := range inputStrings {
		intValue, err := strconv.Atoi(v)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s could not be converted to integer", v)
			os.Exit(1)
		}
		integers[i] = intValue
	}
	return integers
}

func quarterArray(input_arr []int) ([4][]int, error) {
	if len(input_arr) < 4 {
		return [4][]int{}, fmt.Errorf("slice is too small to be divided into 4 parts")
	}

	partSize := len(input_arr) / 4
	remainder := len(input_arr) % 4

	var result [4][]int
	start := 0
	for i := 0; i < 4; i++ {
		end := start + partSize
		if remainder > 0 {
			end++
			remainder--
		}
		result[i] = input_arr[start:end]
		start = end
	}

	return result, nil
}

func sortArray(arr []int, c chan []int) {
	fmt.Println("Will sort: ", arr)
	sort.Ints(arr)
	c <- arr
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	fmt.Println("Input a sequence of ints and I will sort them for you: ")
	// Process text into input []int
	scanner.Scan()
	input_text := scanner.Text()
	input_text = strings.TrimSpace(input_text)
	split_input := strings.Split(input_text, " ")
	user_int_slice := stringsToInt(split_input)

	// quarter input []int
	quartered, err := quarterArray(user_int_slice)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(1)
	}
	// Spawn 4 threads
	c := make(chan []int, 4)
	for _, quarter := range quartered {
		go sortArray(quarter, c)
	}

	combined := []int{}

	for i := 4; i > 0; i-- {
		sorted_ints := <-c
		// the ... is use the []int as a variadic argument
		combined = append(combined, sorted_ints...)
	}
	sort.Ints(combined)
	fmt.Println(combined)
}
