/*
 * Copyright 2002-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.samples.petclinic.web;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.Date;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.springframework.samples.petclinic.Clinic;
import org.springframework.samples.petclinic.Owner;
import org.springframework.samples.petclinic.Pet;
import org.springframework.samples.petclinic.Visit;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.MapBindingResult;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.bind.support.SimpleSessionStatus;

/**
 * Unit tests for {@link VisitController}.
 * 
 * @author Chris Beams
 */
public class VisitControllerTests {

    private VisitController visitController;
    private Clinic clinic;

    private Model model;
    private BindingResult result;
    private SessionStatus status;

    @Before
    public void setUp() {
        model = new ExtendedModelMap();
        result = new MapBindingResult(model.asMap(), "visit");
        status = new SimpleSessionStatus();

        clinic = EasyMock.createMock(Clinic.class);

        visitController = new VisitController(clinic);
    }

    @Test
    public void setupAdd() {
        EasyMock.expect(clinic.loadPet(1)).andReturn(new Pet());
        EasyMock.replay(clinic);

        visitController = new VisitController(clinic);
        visitController.add(1, model);
        assertTrue(model.containsAttribute("visit"));
        assertNotNull(((Visit) model.asMap().get("visit")).getPet());
    }

    @Test
    public void submitAddWithoutBindingErrors() {
        Visit visit = createValidVisit();

        clinic.storeVisit(visit);
        EasyMock.replay(clinic);

        String viewName = visitController.add(visit, result, status);

        assertThat(viewName, equalTo(ViewUtils.getRedirectForOwner(visit.getPet().getOwner())));
    }

    @Test
    public void submitAddWithBindingErrors() {
        Visit visit = createValidVisit();

        clinic.storeVisit(visit);
        EasyMock.replay(clinic);

        result.addError(new FieldError("visit", "description", "is required"));

        String viewName = visitController.add(visit, result, status);

        assertThat(viewName, equalTo(null));
    }

    @Test
    public void submitAddWithValidationErrors() {
        Visit visit = createValidVisit();

        // invalidate the visit object by setting its description property to null
        visit.setDescription(null);

        clinic.storeVisit(visit);
        EasyMock.replay(clinic);

        String viewName = visitController.add(visit, result, status);

        assertThat(viewName, equalTo(null));
    }

    private static Visit createValidVisit() {
        Owner o = new Owner();
        o.setId(99);
        Pet p = new Pet();

        Visit visit = new Visit();
        visit.setDate(new Date());
        visit.setDescription("basic check-up");

        p.setId(55);
        o.addPet(p);
        p.addVisit(visit);

        return visit;
    }
}
