{-
	Copyright (C) 2018 Dr. Alistair Ward

	This file is part of BishBosh.

	BishBosh is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	BishBosh is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with BishBosh.  If not, see <http://www.gnu.org/licenses/>.
-}
{- |
 [@AUTHOR@]	Dr. Alistair Ward

 [@DESCRIPTION@]

	* Itemises the various reasons for terminating a game.

	* Each reason corresponds to a rule in chess.
-}

module BishBosh.Model.GameTerminationReason(
-- * Types
-- ** Data-types
	GameTerminationReason(),
-- * Function
	toResult,
-- ** Constructors
	mkCheckMate,
	mkResignation,
	mkDraw,
-- ** Predicates
	isCheckMateBy,
	isCheckMate,
	isResignation,
	isDraw,
	isDrawByInsufficientMaterial,
	isStaleMate
) where

import qualified	BishBosh.Attribute.LogicalColour	as Attribute.LogicalColour
import qualified	BishBosh.Model.DrawReason		as Model.DrawReason
import qualified	BishBosh.Model.Result			as Model.Result
import qualified	BishBosh.Property.Opposable		as Property.Opposable
import qualified	Control.DeepSeq

-- | The ways in which a game can legally be terminated.
data GameTerminationReason
	= CheckMateOf Attribute.LogicalColour.LogicalColour	-- ^ The /logical colour/ of the /check-mated/ player.
	| ResignationBy Attribute.LogicalColour.LogicalColour	-- ^ The /logical colour/ of the player who resigned.
	| Draw Model.DrawReason.DrawReason
	deriving (Eq, Read, Show)

instance Control.DeepSeq.NFData GameTerminationReason where
	rnf (CheckMateOf logicalColour)		= Control.DeepSeq.rnf logicalColour
	rnf (ResignationBy logicalColour)	= Control.DeepSeq.rnf logicalColour
	rnf (Draw drawReason)			= Control.DeepSeq.rnf drawReason

instance Property.Opposable.Opposable GameTerminationReason where
	getOpposite (CheckMateOf logicalColour)		= CheckMateOf $ Property.Opposable.getOpposite logicalColour
	getOpposite (ResignationBy logicalColour)	= ResignationBy $ Property.Opposable.getOpposite logicalColour
	getOpposite draw				= draw

-- | Convert to a /result/.
toResult :: GameTerminationReason -> Model.Result.Result
toResult gameTerminationReason	= Property.Opposable.getOpposite . Model.Result.mkResult $ case gameTerminationReason of
	CheckMateOf logicalColour	-> Just logicalColour
	ResignationBy logicalColour	-> Just logicalColour
	Draw _				-> Nothing

-- | Constructor.
mkCheckMate :: Attribute.LogicalColour.LogicalColour -> GameTerminationReason
mkCheckMate	= CheckMateOf

-- | Constructor.
mkResignation :: Attribute.LogicalColour.LogicalColour -> GameTerminationReason
mkResignation	= ResignationBy

-- | Constructor.
mkDraw :: Model.DrawReason.DrawReason -> GameTerminationReason
mkDraw	= Draw

-- | Whether the game was won by the specified player.
isCheckMateBy :: Attribute.LogicalColour.LogicalColour -> GameTerminationReason -> Bool
isCheckMateBy logicalColour (CheckMateOf logicalColour')	= logicalColour /= logicalColour'
isCheckMateBy _ _						= False

-- | Whether the game terminated in check-mate.
isCheckMate :: GameTerminationReason -> Bool
isCheckMate (CheckMateOf _)	= True
isCheckMate _			= False

-- | Whether the game was resigned.
isResignation :: GameTerminationReason -> Bool
isResignation (ResignationBy _)	= True
isResignation _			= False

-- | Whether the game was drawn.
isDraw :: GameTerminationReason -> Bool
isDraw (Draw _)	= True
isDraw _	= False

-- | Predicate.
isDrawByInsufficientMaterial :: GameTerminationReason -> Bool
isDrawByInsufficientMaterial (Draw draw)	= draw == Model.DrawReason.insufficientMaterial
isDrawByInsufficientMaterial _			= False

-- | Predicate.
isStaleMate :: GameTerminationReason -> Bool
isStaleMate (Draw draw)	= draw == Model.DrawReason.staleMate
isStaleMate _		= False