package matrix

import (
	"errors"
	"strconv"
	"strings"
)

// Matrix is a grid of ints
type Matrix struct {
	vals [][]int
}

type Pair [2]int

// New creates a new Matrix from a string of numbers
func New(in string) (*Matrix, error) {
	ret := Matrix{}
	rows := strings.Split(in, "\n")
	for i := range rows {
		flds := strings.Fields(rows[i])
		var ints []int
		for j := range flds {
			if v, err := strconv.Atoi(flds[j]); err != nil {
				return &ret, err
			} else {
				ints = append(ints, v)
			}
		}
		ret.vals = append(ret.vals, ints)
	}
	numInRow := -1
	for i := range ret.vals {
		if numInRow != -1 {
			if len(ret.vals[i]) != numInRow {
				return &ret, errors.New("All rows must be equal length")
			}
		}
		numInRow = len(ret.vals[i])
	}
	return &ret, nil
}

// Saddle finds all Saddle Points in the matrix
func (m *Matrix) Saddle() []Pair {
	var ret []Pair
	for i := range m.vals {
		for j := range m.vals[i] {
			val := m.vals[i][j]
			// Check if i,j is a saddle point
			// (Highest in row, lowest in col)
			colTest, rowTest := true, true
			for k := range m.vals {
				if m.vals[k][j] < val {
					colTest = false
					break
				}
			}
			for k := range m.vals[i] {
				if m.vals[i][k] > val {
					rowTest = false
					break
				}
			}
			if colTest && rowTest {
				ret = append(ret, Pair{i, j})
			}
		}
	}
	return ret
}
