package main

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

type Animal interface {
	Eat()
	Move()
	Speak()
}

type Cow struct {
}

func (cow Cow) Eat() {
	fmt.Println("grass")
}

func (cow Cow) Move() {
	fmt.Println("walk")
}

func (cow Cow) Speak() {
	fmt.Println("moo")
}

type Bird struct {
}

func (bird Bird) Eat() {
	fmt.Println("worms")
}

func (bird Bird) Move() {
	fmt.Println("fly")
}

func (bird Bird) Speak() {
	fmt.Println("peep")
}

type Snake struct {
}

func (snake Snake) Eat() {
	fmt.Println("mice")
}

func (snake Snake) Move() {
	fmt.Println("slither")
}

func (snake Snake) Speak() {
	fmt.Println("hsss")
}

func createNewAnimal(animalName string, animalType string, animalMap map[string]Animal)  {
	switch animalType {
	case "cow":
		animalMap[animalName] = Cow{}
	case "bird":
		animalMap[animalName] = Bird{}
	case "snake":
		animalMap[animalName] = Snake{}
	default:
		fmt.Println("Invalid animal type")
		return
	}
	fmt.Println("Created it!")
}

func queryAnimal(animalName string, animalAction string, animalMap map[string]Animal)  {
	animal, ok := animalMap[animalName]
	if !ok {
		fmt.Printf("Could not find animal %s\n", animalName)
		return
	}
	switch animalAction {
	case "eat":
		animal.Eat()
	case "move":
		animal.Move()
	case "speak":
		animal.Speak()
	}

}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	animalMap := make(map[string]Animal)
	
	for  {
		fmt.Print(">")
		var fields []string
		if scanner.Scan() {
			fields = strings.Fields(scanner.Text())
			if len(fields) != 3 {
				fmt.Println("Wrong number of arguments")
				continue
			}
		}
		switch fields[0] {
		case "newanimal":
			createNewAnimal(fields[1], fields[2], animalMap)
		case "query":
			queryAnimal(fields[1], fields[2], animalMap)
		default:
			fmt.Println("Invalid command")
		}
	}
}
