import torch


def validate(model, testloader, criterion, device=None):
    """Function to validate(test) a model

    Args:
        model (:nn.Module): The model use for validation
        testloader (:DataLoader): The training dataloader
        criterion : The loss function
        device (device): The device to use
    Returns:
        (accuracy, test_loss) : the accuracy and the test loss of the test
    """
    if device is None:
        device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    model.to(device)
    test_loss = 0
    accuracy = 0
    for images, labels in testloader:
        images, labels = images.to(device), labels.to(device)
        # output of the test batch
        output = model.forward(images)
        # calculate the test loss and increment the variable
        loss = criterion(output, labels)
        test_loss += loss.item()
        # probabilities since log soft_max is used we need to calculate the exp to get the probabilities
        ps = torch.exp(output)
        # get the highest prob
        predicted_classes = ps.max(dim=1)[1]
        compare_results = predicted_classes == labels.data
        accuracy += compare_results.type(torch.FloatTensor).mean()
    return accuracy, test_loss