private void HandleInputUnselected(BoardLocationEventArgs e, MouseTargetFlags targetType, Cell contents)
        {
            if (e.MouseEvent != BoardMouseEventType.LeftClick && e.MouseEvent != BoardMouseEventType.LeftDragStart &&
                e.MouseEvent != BoardMouseEventType.RightClick && e.MouseEvent != BoardMouseEventType.RightDragStart)
            {
                return;
            }

            var lmb = e.MouseEvent != BoardMouseEventType.RightClick &&
                      e.MouseEvent != BoardMouseEventType.RightDragStart;

            switch (targetType)
            {
            case DeselectedEmptySpace:
                Model.SelectionObject = e.Location;
                Model.SelectionState  = SelectionState.EmptySelected;
                SelectVariationByMouseButton(lmb);
                VisualizeSelectedMove();
                break;

            case DeselectedOwnPiece:
                Model.SelectionObject = e.Location;
                Model.SelectionState  = SelectionState.PieceInHand;
                SelectHighestVariation();
                VisualizeSelectedMove();
                break;

            case DeselectedOwnStack:
                Model.SelectionObject = e.Location;
                SelectVariationByMouseButton(lmb);
                Model.SelectionState = lmb ? SelectionState.PieceInHand : SelectionState.SplitInHand;
                VisualizeSelectedMove();
                break;
            }
        }
        private void ViewOnInputEvent(object sender, BoardLocationEventArgs e)
        {
            if (!Movement.IsValidLocation(e.Location))
            {
                return;
            }
            var contents   = Model.CommittedState[e.Location];
            var targetType = GetMouseTargetType(Model, e.Location, contents);

            switch (Model.SelectionState)
            {
            case SelectionState.Unselected:
                HandleInputUnselected(e, targetType, contents);
                break;

            case SelectionState.EmptySelected:
                HandleInputEmptySelected(e, targetType, contents);
                break;

            case SelectionState.PieceInHand:
                HandleInputPieceInHand(e, targetType, contents);
                break;

            case SelectionState.SplitInHand:
                HandleInputSplitInHand(e, targetType, contents);
                break;

            case SelectionState.MoveSelected:
                HandleInputMoveSelected(e, targetType, contents);
                break;
            }
        }
        private void HandleInputSplitInHand(BoardLocationEventArgs e, MouseTargetFlags targetType, Cell contents)
        {
            if (e.MouseEvent != BoardMouseEventType.LeftClick && e.MouseEvent != BoardMouseEventType.LeftDragEnd &&
                e.MouseEvent != BoardMouseEventType.RightClick && e.MouseEvent != BoardMouseEventType.RightDragEnd &&
                e.MouseEvent != BoardMouseEventType.PartialDropContinueDrag)
            {
                return;
            }

            var lmb = e.MouseEvent != BoardMouseEventType.RightClick &&
                      e.MouseEvent != BoardMouseEventType.RightDragEnd &&
                      e.MouseEvent != BoardMouseEventType.PartialDropContinueDrag;

            switch (targetType)
            {
            case DeselectedEmptySpace:     //not a valid target for this piece -- keep piece in hand
            case DeselectedOwnPiece:
            case DeselectedOpponentPiece:
            case DeselectedOwnStack:
            case DeselectedOpponentStack:
                break;

            case HighlightedEmptySpace:     //valid target for this piece
            case HighlightedOwnPiece:
            case HighlightedOpponentPiece:
            case HighlightedOwnStack:
            case HighlightedOpponentStack:
                Model.SelectionTarget = e.Location;
                SelectLowestVariation();
                Model.SelectionState = SelectionState.MoveSelected;
                VisualizeSelectedMove();
                break;

            case SelectedOwnPiece:     //re-clicked the same piece we just picked up
                Model.SelectionObject   = Location.Undefined;
                Model.SelectionTarget   = Location.Undefined;
                Model.SelectionState    = SelectionState.Unselected;
                Model.SelectedVariation = null;
                VisualizeSelectedMove();
                break;

            case SelectedOwnStack: //re-clicked the same stack we just picked up part of
                if (lmb)           //on left click, put the partial stack back down.
                {
                    Model.SelectionObject   = Location.Undefined;
                    Model.SelectionTarget   = Location.Undefined;
                    Model.SelectionState    = SelectionState.Unselected;
                    Model.SelectedVariation = null;
                }
                else     //on right click, pick up the rest of the stack and make it a full piece
                {
                    SelectHighestVariation();
                    Model.SelectionState = SelectionState.PieceInHand;
                }
                VisualizeSelectedMove();
                break;
            }
        }
        private void HandleInputPieceInHand(BoardLocationEventArgs e, MouseTargetFlags targetType, Cell contents)
        {
            if (e.MouseEvent != BoardMouseEventType.LeftClick && e.MouseEvent != BoardMouseEventType.LeftDragEnd &&
                e.MouseEvent != BoardMouseEventType.RightClick && e.MouseEvent != BoardMouseEventType.RightDragEnd &&
                e.MouseEvent != BoardMouseEventType.PartialDropContinueDrag)
            {
                return;
            }

            var lmb = e.MouseEvent != BoardMouseEventType.RightClick &&
                      e.MouseEvent != BoardMouseEventType.RightDragEnd &&
                      e.MouseEvent != BoardMouseEventType.PartialDropContinueDrag;

            switch (targetType)
            {
            case DeselectedEmptySpace:     //not a valid target for this piece -- keep piece in hand
            case DeselectedOwnPiece:
            case DeselectedOpponentPiece:
            case DeselectedOwnStack:
            case DeselectedOpponentStack:
                break;

            case HighlightedEmptySpace:     //valid target for this piece
            case HighlightedOwnPiece:
            case HighlightedOpponentPiece:
            case HighlightedOwnStack:
            case HighlightedOpponentStack:
                Model.SelectionTarget = e.Location;
                Model.SelectionState  = SelectionState.MoveSelected;
                SelectVariationByMouseButton(lmb);
                VisualizeSelectedMove();
                break;

            case SelectedOwnPiece:     //re-clicked the same piece we just picked up, or dropped it back where we picked it up from
            case SelectedOwnStack:
                Model.SelectionTarget   = Location.Undefined;
                Model.SelectionObject   = Location.Undefined;
                Model.SelectionState    = SelectionState.Unselected;
                Model.SelectedVariation = null;
                VisualizeSelectedMove();
                break;
            }
        }
        private void HandleInputMoveSelected(BoardLocationEventArgs e, MouseTargetFlags targetType, Cell contents)
        {
            if (e.MouseEvent != BoardMouseEventType.LeftClick && e.MouseEvent != BoardMouseEventType.LeftDragStart &&
                e.MouseEvent != BoardMouseEventType.RightClick && e.MouseEvent != BoardMouseEventType.RightDragStart)
            {
                return;
            }

            var lmb = e.MouseEvent != BoardMouseEventType.RightClick &&
                      e.MouseEvent != BoardMouseEventType.RightDragStart;

            switch (targetType)
            {
            case DeselectedEmptySpace:     //undoing selected move and changing to a place/block
                Model.SelectionObject = e.Location;
                Model.SelectionTarget = Location.Undefined;
                Model.SelectionState  = SelectionState.EmptySelected;
                SelectVariationByMouseButton(lmb);
                VisualizeSelectedMove();
                break;

            case TargetedEmptySpace:     //picking dropped piece back up to place it somewhere else on LMB
            case SelectedOwnPiece:       //or rotating selection options on RMB
            case TargetedOwnPiece:
            case TargetedOpponentPiece:
            case SelectedOwnStack:
            case TargetedOwnStack:
            case TargetedOpponentStack:
                if (lmb)
                {
                    Model.SelectionTarget = Location.Undefined;
                    if (Model.SelectedVariation == Model.MaxVariation)
                    {
                        //pick up entire piece
                        Model.SelectionState = SelectionState.PieceInHand;
                        SelectHighestVariation();
                    }
                    else
                    {
                        //partial stack was placed so pick up partial stack
                        Model.SelectionState = SelectionState.SplitInHand;
                        SelectLowestVariation();
                    }
                }
                else
                {
                    SelectNextVariation();
                    //Model.SelectionState = Model.SelectedVariation == Model.MaxVariation
                    //    ? SelectionState.PieceInHand
                    //    : SelectionState.SplitInHand;
                }
                VisualizeSelectedMove();
                break;

            case DeselectedOwnPiece:     //abandoning existing move and picking up a new piece
                Model.SelectionObject = e.Location;
                Model.SelectionTarget = Location.Undefined;
                Model.SelectionState  = SelectionState.PieceInHand;
                SelectHighestVariation();
                VisualizeSelectedMove();
                break;

            case DeselectedOwnStack:     //abandoning existing move and picking up all or part of a new stack
                Model.SelectionObject = e.Location;
                Model.SelectionTarget = Location.Undefined;
                SelectVariationByMouseButton(lmb);
                Model.SelectionState = lmb ? SelectionState.PieceInHand : SelectionState.SplitInHand;
                VisualizeSelectedMove();
                break;
            }
        }