{-# LANGUAGE UnicodeSyntax, TemplateHaskell #-}
-- | record a match to a tape which is serialisable
module SoccerFun.Tape where

import Prelude.Unicode
import Data.DeriveTH
import Data.Binary
import SoccerFun.MatchControl
import SoccerFun.Player
import SoccerFun.Types
import SoccerFun.Field
import SoccerFun.Geometry
import SoccerFun.Ball
import SoccerFun.RefereeAction
import Control.Monad

instance Binary Match where
	put m = do
		put $ team1 m
		put $ team2 m
		put $ theBall m
		put $ theField m
		put $ playingHalf m
		put $ playingTime m
		put $ score m
		put $ unittime m
	get = do
		team1  get
		team2  get
		theBall  get
		theField  get
		playingHalf  get
		playingTime  get
		score  get
		unittime  get
		return $ Match
			{team1       = team1,
	 	 	 team2       = team2,
	 	 	 theBall     = theBall,
	 	 	 theField    = theField,
	 	 	 theReferee  = undefined,
	 	 	 playingHalf = playingHalf,
	 	 	 playingTime = playingTime,
	 	 	 score       = score,
	 	 	 seed        = undefined,
	 	 	 unittime    = unittime}

instance Binary Player where
	put p = do
		put $ playerID p
		put $ name p
		put $ height p
		put $ pos p
		put $ speed p
		put $ nose p
		put $ skills p
		put $ effect p
		put $ stamina p
		put $ health p
	get = do
		playerID  get
		name  get
		height  get
		pos  get
		speed  get
		nose  get
		skills  get
		effect  get
		stamina  get
		health  get
		return $ Player
			{playerID = playerID,
	 	 	 name = name,
	 	 	 height = height,
	 	 	 pos = pos,
	 	 	 speed = speed,
	 	 	 nose = nose,
	 	 	 skills = skills,
	 	 	 effect = effect,
	 	 	 stamina = stamina,
	 	 	 health = health,
	 	 	 brain = undefined}

$( derive makeBinary ''Half )
$( derive makeBinary ''Field )
$( derive makeBinary ''Position3D )
$( derive makeBinary ''Ball )
$( derive makeBinary ''BallState )
$( derive makeBinary ''PlayerID )
$( derive makeBinary ''Position )
$( derive makeBinary ''Speed )
$( derive makeBinary ''Skill )
$( derive makeBinary ''PlayerEffect )
$( derive makeBinary ''Success )
$( derive makeBinary ''Speed3D )
$( derive makeBinary ''FeintDirection )
$( derive makeBinary ''RefereeAction )
$( derive makeBinary ''PlayerAction )
$( derive makeBinary ''Edge )
$( derive makeBinary ''ATeam )
$( derive makeBinary ''Reprimand )


data Tape = Tape [Step]

magic = "SoccerFun tape"
version = "0.3.7"

instance Binary Tape where
	put (Tape steps) = do
		put magic
		put version
		put steps
	get = do
		let checkMagic m = when (not $ m  magic) (error "This file does not contain a SoccerFun tape!")
		checkMagic =<< get
		let checkVersion v = when (not $ v  version) (error $ "Incompatible tape version: "  show v)
		checkVersion =<< get
		liftM Tape get

recordMatch  Match  Tape
recordMatch m = Tape $ recordMatch' (([],[]), m) where

	recordMatch'  (([RefereeAction],[PlayerWithAction]),Match)  [(([RefereeAction],[PlayerWithAction]),Match)]
	recordMatch' = takeWhile matchRunning  iterate (stepMatch  snd)

	matchRunning (actions,match) = playingTime match > 0