package fic

import (
	"fmt"
)

// statLine is a line of statistics for the file stats.json exposed to players.
type statLine struct {
	Tip    string `json:"tip"`
	Total  int    `json:"total"`
	Solved int    `json:"solved"`
	Tried  int    `json:"tried"`
	Tries  int    `json:"tries"`
}

// teamStats represents the structure of stats.json.
type teamStats struct {
	Levels []statLine         `json:"levels"`
	Themes map[int64]statLine `json:"themes"`
}

// GetLevel
func (s *teamStats) GetLevel(level int) *statLine {
	level -= 1

	for len(s.Levels) <= level {
		s.Levels = append(s.Levels, statLine{
			fmt.Sprintf("Level %d", (len(s.Levels) + 1)),
			0,
			0,
			0,
			0,
		})
	}

	return &s.Levels[level]
}

// GetStats generates statistics for the Team.
func (t Team) GetStats() (interface{}, error) {
	return GetTeamsStats(&t)
}

// GetTeamsStats returns statistics limited to the given Team.
func GetTeamsStats(t *Team) (interface{}, error) {
	stat := teamStats{
		[]statLine{},
		map[int64]statLine{},
	}

	if themes, err := GetThemes(); err != nil {
		return nil, err
	} else {
		for _, theme := range themes {
			total := 0
			solved := 0
			tried := 0
			tries := 0

			if exercices, err := theme.GetExercices(); err != nil {
				return nil, err
			} else {
				for _, exercice := range exercices {
					var lvl int
					if lvl, err = exercice.GetLevel(); err != nil {
						return nil, err
					}
					sLvl := stat.GetLevel(lvl)

					total += 1
					sLvl.Total += 1

					if t != nil {
						if b := t.HasSolved(exercice); b != nil {
							solved += 1
							sLvl.Solved += 1
						}
					} else {
						if n, _ := exercice.IsSolved(); n > 0 {
							solved += n
							sLvl.Solved += 1
						}
					}

					try := NbTry(t, exercice)
					if try > 0 {
						tried += 1
						tries += try
						sLvl.Tried += 1
						sLvl.Tries += try
					}
				}
			}

			stat.Themes[theme.Id] = statLine{
				theme.Name,
				total,
				solved,
				tried,
				tries,
			}
		}

		return stat, nil
	}
}
