package main

import (
	"bufio"
	"bytes"
	"flag"
	"log"
	"os"
	"sort"
	"strconv"
)

const (
	maxBufSize = 100 * 1024 * 1024 // 1MB
)

var (
	reader *bufio.Scanner
	file   = flag.String("i", "", "input file (stdin will be used by default)")
	cota   = flag.Int("c", 1, "max number of mensagens by sender")
)

type Record struct {
	Sender string
	Count  int
}

func main() {
	flag.Parse()
	if *file != "" {
		f, err := os.Open(*file)
		if err != nil {
			log.Fatalln(err)
		}
		defer f.Close()
		reader = bufio.NewScanner(f)
	} else {
		reader = bufio.NewScanner(os.Stdin)
	}

	reader.Buffer(make([]byte, maxBufSize), maxBufSize)

	list := make(map[string]int)
	for reader.Scan() {
		processLine(reader.Bytes(), list)
	}

	report(list)
}

func processLine(line []byte, list map[string]int) {
	_, part, ok := bytes.Cut(line[21:], []byte("; from=<"))
	if !ok {
		return
	}
	part, _, ok = bytes.Cut(part, []byte("> to="))
	if !ok {
		return
	}
	if _, ok = list[string(part)]; !ok {
		list[string(part)] = 1
		return
	}

	list[string(part)]++
}

func report(list map[string]int) {
	records := make([]Record, 0, len(list))
	for k, v := range list {
		if v < *cota {
			continue
		}
		records = append(records, Record{k, v})
	}

	sort.Slice(records, func(i, j int) bool { return records[i].Count > records[j].Count })

	for i := range records {
		_, _ = os.Stdout.WriteString(strconv.Itoa(records[i].Count) + "\t" + records[i].Sender + "\n")
	}
}
