package main

import (
	"fmt"
	"os"
	"strings"
)

func printUsage() {
	fmt.Println("Usage: day11 <string> [add-amt]")
	fmt.Println("If add-amt isn't given, we just add 1")
	os.Exit(1)
}

func main() {
	args := os.Args
	if len(args) < 2 {
		printUsage()
	}
	var orig string
	orig = args[1]

	var valid bool
	for !valid {
		orig = addOneToString(orig)
		valid = testPassword(orig)
	}
	fmt.Println(orig)
}

func addOneToString(s string) string {
	lastPlace := s[len(s)-1]
	ret := s[:len(s)-1]
	if lastPlace == 'z' {
		lastPlace = 'a'
		ret = addOneToString(s[:len(s)-1])
	} else {
		lastPlace++
	}
	return ret + string(lastPlace)
}

func testPassword(s string) bool {
	if hasValidChars(s) && hasStraight(s) && hasDoubles(s) {
		return true
	}
	return false
}

// Test if string contains only valid chars
func hasValidChars(s string) bool {
	if strings.Count(s, "i") > 0 {
		return false
	}
	if strings.Count(s, "o") > 0 {
		return false
	}
	if strings.Count(s, "l") > 0 {
		return false
	}
	return true
}

// Test if string has a 3 char straight
func hasStraight(s string) bool {
	for i := range s {
		if i > 1 {
			if (s[i-2] == s[i]-2) && (s[i-1] == s[i]-1) {
				return true
			}
		}
	}
	return false
}

// Test if string has 2 doubles
func hasDoubles(s string) bool {
	if i := hasDouble(s); i >= 0 {
		return (hasDouble(s[i+2:]) >= 0)
	}
	return false
}

// Returns index of first double in string
// -1 if there isn't one
func hasDouble(s string) int {
	for i := range s {
		if i > 0 {
			if s[i-1] == s[i] {
				return i - 1
			}
		}
	}
	return -1
}