{-# LANGUAGE UnicodeSyntax, TypeSynonymInstances, ExistentialQuantification #-}
{-| This module defines the Soccer-Fun API that is concerned with teams.
	All available teams are collected in this module (allAvailableTeams).
module SoccerFun.Team where

import SoccerFun.Player
import SoccerFun.Types
import SoccerFun.Geometry
import SoccerFun.Prelude
import Data.List ((\\), nub, sort)
import SoccerFun.Field

type Team = [Player] -- ^ the fielders are supposed to have different numbers, and all not equal to 1

validateTeam  Team  Team
validateTeam team = map validatePlayer team
--	validatePlayer ∷ Player → Player
	validatePlayer (fb@Player{height=height})
		= fb {height = height `boundedBy` (minHeight,maxHeight)
			  , stamina = maxStamina
			  , health = maxHealth
replaceInTeam  [Player]  Team  Team
replaceInTeam fbs team = (team \\ fbs) ++ fbs

getTeam  ClubName  [Team]  Team
getTeam cn teams = case [team | team<-teams, nameOf team==cn] of
	(team:_)  team
	_  error ("Team " ++ show cn ++ " does not seem to exist.\n")

class Mirror a where mirror  Field  a  a

instance NameOf Team where
	nameOf players
		= case players of
			(fb:_)  nameOf (playerID fb)
			none  error "nameOf[Team]: applied to empty team.\n"

isValidTeam  Team  Bool
isValidTeam team = length clubNames == 1
						  (null keepers || isValidKeeper (head keepers))
						  all isValidPlayer players
						  sort (map nrOf players) == sort (nub (map nrOf players))
						  not (elem 1 (map nrOf fielders))
	(keepers,fielders) = spanfilter isKeeper team
	clubNames = nub (map clubOf players)
	clubName' = head clubNames  String
	players = keepers ++ fielders
	clubOf fb = clubName (playerID fb)
	nrOf fb = playerNo (playerID fb)
	isValidKeeper fb = (playerID fb) == PlayerID {clubName=clubName',playerNo=1}
	isValidPlayer fb = clubOf fb == clubName'

instance Other ATeam where
	other Team1 = Team2
	other Team2 = Team1

instance Mirror a  Mirror [a] where mirror field as = map (mirror field) as
instance Mirror Player where mirror field fb = fb {pos = mirror field (pos fb)
                                                              , nose = mirror field (nose fb)
                                                              , speed = mirror field (speed fb)
instance Mirror Position where mirror field pos = Position {px = (flength field) - (px pos)
                                                          ,py = (fwidth field) - (py pos)
instance Mirror Speed where mirror field speed = speed {direction = mirror field (direction speed)}
instance Mirror Angle where mirror field angle = if (angle >= pi) then (3.0*pi - angle) else (pi - angle)