package main

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

func main() {
	inp := StdinToStringSlice()
	//part1(inp)
	part2(inp)
}

var overlaps map[string]bool

func part1(inp []string) {
	overlaps = make(map[string]bool)
	var allClaims []claim
	for _, v := range inp {
		c := NewClaim(v)
		allClaims = append(allClaims, *c)
	}
	for _, i := range allClaims {
		for _, j := range allClaims {
			if i.ID == j.ID {
				continue
			}
			i.findOverlaps(&j)
		}
	}
	fmt.Printf("Overlapping Spots: %d\n", len(overlaps))
}

func part2(inp []string) {
	var allClaims []claim
	for _, v := range inp {
		c := NewClaim(v)
		allClaims = append(allClaims, *c)
	}
	for _, i := range allClaims {
		var fail bool
		for _, j := range allClaims {
			if i.ID == j.ID {
				continue
			}
			if i.intersects(&j) {
				fail = true
				break
			}
		}
		if !fail {
			fmt.Println("Doesn't overlap: " + i.ID)
			return
		}
	}
}

type claim struct {
	ID            string
	X, Y          int
	Width, Height int
	Spots         []string
}

func NewClaim(inp string) *claim {
	parts := strings.Split(inp, " ")
	pos := strings.Split(strings.Trim(parts[2], ":"), ",")
	size := strings.Split(parts[3], "x")
	x, y, w, h := Atoi(pos[0]), Atoi(pos[1]), Atoi(size[0]), Atoi(size[1])
	var spots []string
	for i := x; i < (x + w); i++ {
		for j := y; j < (y + h); j++ {
			spots = append(spots, fmt.Sprintf("%d;%d", i, j))
		}
	}
	return &claim{
		ID:     parts[0][1:],
		X:      x,
		Y:      y,
		Width:  w,
		Height: h,
		Spots:  spots,
	}
}

func (c *claim) intersects(other *claim) bool {
	for _, i := range c.Spots {
		for _, j := range other.Spots {
			if i == j {
				return true
			}
		}
	}
	return false
}

func (c *claim) findOverlaps(other *claim) bool {
	var ret bool
	for _, i := range c.Spots {
		for _, j := range other.Spots {
			if i == j {
				overlaps[i] = true
				ret = true
			}
		}
	}
	return ret
}

func StdinToStringSlice() []string {
	var input []string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		input = append(input, scanner.Text())
	}
	return input
}

func Atoi(i string) int {
	var ret int
	var err error
	if ret, err = strconv.Atoi(i); err != nil {
		log.Fatal("Invalid Atoi")
	}
	return ret
}
