private CommandResponse ExecuteCreateComment(CreateCommentCommand command)
        {
            var comment = new Comment
            {
                Id        = Guid.NewGuid(),
                Timestamp = DateTime.Now,
                Author    = command.IssuedBy,
                Text      = command.Text
            };

            foreach (var q in Questions)
            {
                if (q.Id == command.QuestionOrAnswerId)
                {
                    q.Comments.Add(comment);
                    return(CommandResponse.Success(comment));
                }

                foreach (var a in q.Answers)
                {
                    if (a.Id == command.QuestionOrAnswerId)
                    {
                        a.Comments.Add(comment);
                        return(CommandResponse.Success(comment));
                    }
                }
            }
            return(CommandResponse.Failure($"Question or answer with id {command.QuestionOrAnswerId} does not exist."));
        }
        private CommandResponse ExecuteDeleteQuestion(DeleteQuestionCommand command)
        {
            var existingQuestion = Questions.FirstOrDefault(q => q.Id == command.QuestionId);

            if (existingQuestion == null)
            {
                return(CommandResponse.Failure($"Question {command.QuestionId} doesn't exist."));
            }
            Questions.Remove(existingQuestion);
            return(CommandResponse.Success());
        }
 private CommandResponse ExecuteAcceptAnswerCommand(AcceptAnswerCommand command)
 {
     foreach (var q in Questions)
     {
         var answer = q.Answers.SingleOrDefault(a => a.Id == command.AnswerId);
         if (answer != null)
         {
             q.AcceptedAnswerId = answer.Id;
             return(CommandResponse.Success(answer));
         }
     }
     return(CommandResponse.Failure($"Answer {command.AnswerId} doesn't exist."));
 }
        private CommandResponse ExecuteEditComment(EditCommentCommand command)
        {
            var existingComment = Questions.SelectMany(q => q.Comments).Concat(Questions.SelectMany(q => q.Answers.SelectMany(a => a.Comments)))
                                  .SingleOrDefault(c => c.Id == command.CommentId);

            if (existingComment == null)
            {
                return(CommandResponse.Failure($"Comment with id {command.CommentId} does not exist."));
            }

            existingComment.Text = command.Text;
            return(CommandResponse.Success(existingComment));
        }
        private CommandResponse ExecuteEditAnswer(EditAnswerCommand command)
        {
            var existingAnswer = Questions.SelectMany(q => q.Answers).SingleOrDefault(a => a.Id == command.AnswerId);

            if (existingAnswer == null)
            {
                return(CommandResponse.Failure($"Answer {command.AnswerId} doesn't exist."));
            }

            existingAnswer.History.Add(new PostHistoryItem
            {
                Author = existingAnswer.Author,
                Text   = existingAnswer.Text
            });

            existingAnswer.Text = command.Text;
            return(CommandResponse.Success(existingAnswer));
        }
        private CommandResponse ExecuteVoteQuestionCommand(VoteQuestionCommand command)
        {
            var existingQuestion = Questions.FirstOrDefault(q => q.Id == command.QuestionId);

            if (existingQuestion == null)
            {
                return(CommandResponse.Failure($"Question {command.QuestionId} doesn't exist."));
            }

            existingQuestion.Votes.Add(new Vote
            {
                Author    = command.IssuedBy,
                Id        = Guid.NewGuid(),
                Timestamp = DateTime.Now,
                Direction = command.VoteDirection
            });
            return(CommandResponse.Success(existingQuestion));
        }
        private CommandResponse ExecuteVoteAnswer(VoteAnswerCommand command)
        {
            var existingAnswer = Questions.SelectMany(q => q.Answers).SingleOrDefault(a => a.Id == command.AnswerId);

            if (existingAnswer == null)
            {
                return(CommandResponse.Failure($"Answer {command.AnswerId} doesn't exist."));
            }

            existingAnswer.Votes.Add(new Vote
            {
                Author    = command.IssuedBy,
                Id        = Guid.NewGuid(),
                Timestamp = DateTime.Now,
                Direction = command.VoteDirection
            });

            return(CommandResponse.Success(existingAnswer));
        }
        private CommandResponse ExecuteEditQuestion(EditQuestionCommand command)
        {
            var existingQuestion = Questions.FirstOrDefault(q => q.Id == command.QuestionId);

            if (existingQuestion == null)
            {
                return(CommandResponse.Failure($"Question {command.QuestionId} doesn't exist."));
            }

            existingQuestion.History.Add(new PostHistoryItem
            {
                Author = existingQuestion.Author,
                Text   = existingQuestion.Text
            });

            existingQuestion.Title = command.Title;
            existingQuestion.Text  = command.Text;
            return(CommandResponse.Success(existingQuestion));
        }
        public CommandResponse Execute(CommandBase command)
        {
            switch (command)
            {
            case EditQuestionCommand editQuestion:
                return(ExecuteEditQuestion(editQuestion));

            case CreateQuestionCommand createQuestion:
                return(ExecuteCreateQuestion(createQuestion));

            case DeleteQuestionCommand deleteQuestion:
                return(ExecuteDeleteQuestion(deleteQuestion));

            case VoteQuestionCommand voteQuestion:
                return(ExecuteVoteQuestionCommand(voteQuestion));

            case CreateAnswerCommand createAnswer:
                return(ExecuteCreateAnswer(createAnswer));

            case EditAnswerCommand editAnswer:
                return(ExecuteEditAnswer(editAnswer));

            case DeleteAnswerCommand deleteAnswer:
                return(ExecuteDeleteAnswer(deleteAnswer));

            case VoteAnswerCommand voteAnswer:
                return(ExecuteVoteAnswer(voteAnswer));

            case AcceptAnswerCommand acceptAnswer:
                return(ExecuteAcceptAnswerCommand(acceptAnswer));

            case CreateCommentCommand createComment:
                return(ExecuteCreateComment(createComment));

            case EditCommentCommand editComment:
                return(ExecuteEditComment(editComment));

            case DeleteCommentCommand deleteComment:
                return(ExecuteDeleteComment(deleteComment));
            }
            return(CommandResponse.Failure($"Command {command.GetType().Name} has no handlers"));
        }
        private CommandResponse ExecuteCreateAnswer(CreateAnswerCommand command)
        {
            var existingQuestion = Questions.FirstOrDefault(q => q.Id == command.QuestionId);

            if (existingQuestion == null)
            {
                return(CommandResponse.Failure($"Question {command.QuestionId} doesn't exist."));
            }

            var answer = new Answer
            {
                Author    = command.IssuedBy,
                Id        = Guid.NewGuid(),
                Timestamp = DateTime.Now,
                Text      = command.Text
            };

            existingQuestion.Answers.Add(answer);

            return(CommandResponse.Success(answer));
        }
        private CommandResponse ExecuteDeleteComment(DeleteCommentCommand command)
        {
            foreach (var q in Questions)
            {
                var existingComment = q.Comments.SingleOrDefault(c => c.Id == command.CommentId);
                if (existingComment != null)
                {
                    q.Comments.Remove(existingComment);
                    return(CommandResponse.Success());
                }

                foreach (var a in q.Answers)
                {
                    existingComment = a.Comments.SingleOrDefault(c => c.Id == command.CommentId);
                    if (existingComment != null)
                    {
                        a.Comments.Remove(existingComment);
                        return(CommandResponse.Success());
                    }
                }
            }
            return(CommandResponse.Failure($"Comment with id {command.CommentId} does not exist."));
        }