package romannumerals

import (
	"errors"
	"strings"
)

// TestVersion tells exercism which tests to use
const TestVersion = 1

// ToRomanNumeral takes an int and returns it's roman numberal string value
// Or an error if it can't be done.
func ToRomanNumeral(arabic int) (string, error) {
	if arabic <= 0 || arabic > 3999 {
		return "", errors.New("Invalid number given")
	}
	var ret string
	var err error
	var care int
	place := 1
	for ; arabic > 0; arabic = (arabic - care) / 10 {
		care = arabic % 10
		ret = getRomanChar(care, place) + ret
		place *= 10
	}
	if strings.Contains(ret, "?") {
		err = errors.New("Invalid number given")
	}
	return ret, err
}

func getRomanChar(dg, pl int) string {
	switch {
	case dg <= 0:
		return ""
	case dg < 4:
		return strings.Repeat(getOnesPlaceChar(pl), dg)
	case dg == 4:
		return getOnesPlaceChar(pl) + getFivesPlaceChar(pl)
	case dg < 9:
		return getFivesPlaceChar(pl) + getRomanChar(dg-5, pl)
	case dg == 9:
		return getOnesPlaceChar(pl) + getOnesPlaceChar(pl*10)
	}
	return "?"
}

func getOnesPlaceChar(pl int) string {
	switch pl {
	case 1:
		return "I"
	case 10:
		return "X"
	case 100:
		return "C"
	case 1000:
		return "M"
	}
	return "?"
}

func getFivesPlaceChar(pl int) string {
	switch pl {
	case 1:
		return "V"
	case 10:
		return "L"
	case 100:
		return "D"
	}
	return "?"
}
