/**
 * Copyright (c) 2006 Red Hat, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Component of: Red Hat Application Server
 * 
 * Initial Developers: Greg Lapouchnian
 *                     Patrick Smith
 *
 */

package olstore.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import olstore.domain.logic.OlstoreFacade;
import olstore.dto.PropertyValue;
import olstore.dto.TypeValue;

import org.springframework.validation.BindException;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

/**
 * A simple form controller to handle creating a new type.
 */
public class CreateTypeController extends SimpleFormController {

    // Olstore instance injected by Spring.
    private OlstoreFacade olstore;

    /**
     * Creates a new controller and sets the class to use as a backing object
     * as well as views, and validation.
     *
     */
    public CreateTypeController() {
        setSessionForm(true);
        setValidateOnBinding(false);
        setCommandClass(TypeValue.class);
        setFormView("createType");
        setSuccessView("createType");
    }

    /**
     * Spring method for dependency injection.
     * @param olstore supplied via spring.
     */
    public void setOlstore(OlstoreFacade olstore) {
        this.olstore = olstore;
    }

    /**
     * Returns the object that will be used as the form's backing object.
     * 
     * @param request the HttpServletRequest object.
     * @return the object that this form will use as its backing object.
     */
    protected Object formBackingObject(HttpServletRequest request) throws Exception {
        TypeValue type = new TypeValue();
        ArrayList props = new ArrayList();
        props.add ( new PropertyValue() );
        type.setProperties(props);
        return type;
    }

    /**
     * Sets what validation is to be done on the command object's fields.
     * 
     * @param request the HttpServletRequest
     * @param command the command object used as the backing object.
     * @param errors where the errors are reported if validation fails.
     */
    protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors)
            throws Exception {

        System.out.println("need to validate");
        if(!isFormChangeRequest(request)) {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "NAME_REQUIRED", "Type name is required.");
            TypeValue type = (TypeValue)command;
            Iterator i = type.getProperties().iterator();
            while(i.hasNext()) {
                PropertyValue prop = (PropertyValue)i.next();
                if(prop.getName() == null || prop.getName().length() == 0) {
                    errors.rejectValue("properties", "PROP_REQUIRED", "Property name is required.");
                }
            }
        }
    }

    /**
     * The initial model to be used in this form.
     * 
     * @param request the HttpServletRequest object.
     * @return a map that represents the model to be used in the view.
     */
    protected Map referenceData(HttpServletRequest request) throws Exception {
        Map model = ControllerHelper.initModel(request, olstore);
        model.put("page_title", "Create New Type - Olstore");
        model.put("types", this.olstore.getTypes());
        return model;
    }

    /**
     * Handles the submission of the simple form object, and returns a new
     * model and view to represent the changes.
     * 
     * @param request the HttpServletRequest
     * @param response the HttpServletResponse
     * @param command the backing object of this form.
     * @param errors the errors to report for this form's validation.
     * @return a new model and view to represent the form.
     */
    protected ModelAndView onSubmit(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    Object command, 
                                    BindException errors) throws Exception {
        // supply the errors to the view inside the model map
        Map model = errors.getModel();
        // add the reference data once again so it will continue to be displayed
        model.putAll(referenceData(request));
        
        TypeValue type = (TypeValue) command;
        try {
            this.olstore.saveType(type);
        }
        catch (Exception ex) {
            model.put("error", "There was an error trying to save your new type.");
            return showForm(request, response, errors, model);
        }
        // refresh the types displayed on the sidebar to include the newly added one
        model.put("types", this.olstore.getTypes());
        
        model.put("message", "New type successfully saved.");
        return new ModelAndView("createType", model);
    }

    /**
     * Called when the form is changed so that if a new property is needed
     * it can be properly added to the backing command object.
     * 
     * @param request the HttpServletRequest.
     * @param response the HttpServletResponse
     * @param command the backing objecdt of this form.
     */
    protected void onFormChange(HttpServletRequest request,
                                HttpServletResponse response,
                                Object command) throws Exception {
        TypeValue type = (TypeValue)command;
        // add another property to the object
        type.getProperties().add(new PropertyValue());
    }

    /**
     * Checks to see if the request is to change the form, or an actual submit.
     * 
     * @param request the HttpServletRequest
     * @return true if the request is to change the form, false otherwise.
     */
    protected boolean isFormChangeRequest(HttpServletRequest request) {
        return request.getParameter("add-property") != null;
    }

}
