/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.wicket.examples.wizard;

import java.util.Arrays;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.extensions.wizard.AjaxWizardButtonBar;
import org.apache.wicket.extensions.wizard.StaticContentStep;
import org.apache.wicket.extensions.wizard.Wizard;
import org.apache.wicket.extensions.wizard.WizardModel;
import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.ListMultipleChoice;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
import org.apache.wicket.markup.html.form.validation.EqualInputValidator;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.validation.ValidationError;
import org.apache.wicket.validation.validator.EmailAddressValidator;


/**
 * This wizard shows some basic form use. It uses custom panels for the form elements, and a single
 * domain object ({@link User}) as it's subject. Also, the user roles step}is an optional step, that
 * will only be executed when assignRoles is true (and that value is edited in the user details
 * step).
 * <br>
 * Buttons are using Ajax requests.
 * 
 * @author Eelco Hillenius
 */
public class NewUserWizard extends Wizard
{
	/**
	 * The confirmation step.
	 */
	private final class ConfirmationStep extends StaticContentStep
	{
		/**
		 * Construct.
		 */
		public ConfirmationStep()
		{
			super(true);
			IModel<User> userModel = new Model<>(user);
			setTitleModel(new ResourceModel("confirmation.title"));
			setSummaryModel(new StringResourceModel("confirmation.summary", this, userModel));
			setContentModel(new StringResourceModel("confirmation.content", this, userModel));
		}
	}

	/**
	 * The user details step.
	 */
	private final class UserDetailsStep extends WizardStep
	{
		/**
		 * Construct.
		 */
		public UserDetailsStep()
		{
			setTitleModel(new ResourceModel("confirmation.title"));
			setSummaryModel(new StringResourceModel("userdetails.summary", this, new Model<>(
				user)));
			add(new RequiredTextField<>("user.firstName"));
			add(new RequiredTextField<>("user.lastName"));
			add(new TextField<>("user.department"));
			add(new CheckBox("assignRoles"));
		}
	}

	/**
	 * The user name step.
	 */
	private final class UserNameStep extends WizardStep
	{
		/**
		 * Construct.
		 */
		public UserNameStep()
		{
			super(new ResourceModel("username.title"), new ResourceModel("username.summary"));

			add(new RequiredTextField<>("user.userName"));

			FormComponent<String> email = new RequiredTextField<String>("user.email").add(EmailAddressValidator.getInstance());
			add(email);

			TextField<String> emailRepeat = new TextField<>("emailRepeat",
				new Model<String>());
			add(emailRepeat);

			add(new EqualInputValidator(email, emailRepeat));
		}
	}

	/**
	 * The user details step.
	 */
	private final class UserRolesStep extends WizardStep implements ICondition
	{
		/**
		 * Construct.
		 */
		public UserRolesStep()
		{
			super(new ResourceModel("userroles.title"), null);
			setSummaryModel(new StringResourceModel("userroles.summary", this,
				new Model<>(user)));
			final ListMultipleChoice<String> rolesChoiceField = new ListMultipleChoice<>(
				"user.roles", allRoles);
			add(rolesChoiceField);
			final TextField<String> rolesSetNameField = new TextField<>("user.rolesSetName");
			add(rolesSetNameField);
			add(new AbstractFormValidator()
			{
				@Override
				public FormComponent[] getDependentFormComponents()
				{
					// name and roles don't have anything to validate,
					// so might as well just skip them here
					return null;
				}

				@Override
				public void validate(Form<?> form)
				{
					String rolesInput = rolesChoiceField.getInput();
					if (rolesInput != null && !rolesInput.isEmpty())
					{
						final String rolesSetNameFieldInput = rolesSetNameField.getInput();
						if (rolesSetNameFieldInput == null || rolesSetNameFieldInput.isEmpty())
						{
							rolesSetNameField.error(new ValidationError().addKey("error.noSetNameForRoles"));
						}
					}
				}
			});
		}

		@Override
		public boolean evaluate()
		{
			return assignRoles;
		}
	}

	/** cheap ass roles database. */
	private static final List<String> allRoles = Arrays.asList("admin", "user", "moderator",
		"joker", "slacker");

	/** Whether the assign roles step should be executed. */
	private boolean assignRoles = false;

	/** The user we are editing. */
	private User user;

	/**
	 * Construct.
	 * 
	 * @param id
	 *            The component id
	 */
	public NewUserWizard(String id)
	{
		super(id);

		// create a blank user
		user = new User();

		setDefaultModel(new CompoundPropertyModel<>(this));
		WizardModel model = new WizardModel();
		model.add(new UserNameStep());
		model.add(new UserDetailsStep());
		model.add(new UserRolesStep());
		model.add(new ConfirmationStep());

		// initialize the wizard with the wizard model we just built
		init(model);
	}

	/**
	 * Use Ajax buttons.
	 */
	@Override
	protected Component newButtonBar(String id)
	{
		return new AjaxWizardButtonBar(id, this);
	}

	/**
	 * Gets user.
	 * 
	 * @return user
	 */
	public User getUser()
	{
		return user;
	}

	/**
	 * Gets assignRoles.
	 * 
	 * @return assignRoles
	 */
	public boolean isAssignRoles()
	{
		return assignRoles;
	}

	/**
	 * @see org.apache.wicket.extensions.wizard.Wizard#onCancel()
	 */
	@Override
	public void onCancel()
	{
		setResponsePage(Index.class);
	}

	/**
	 * @see org.apache.wicket.extensions.wizard.Wizard#onFinish()
	 */
	@Override
	public void onFinish()
	{
		setResponsePage(Index.class);
	}

	/**
	 * Sets assignRoles.
	 * 
	 * @param assignRoles
	 *            assignRoles
	 */
	public void setAssignRoles(boolean assignRoles)
	{
		this.assignRoles = assignRoles;
	}

	/**
	 * Sets user.
	 * 
	 * @param user
	 *            user
	 */
	public void setUser(User user)
	{
		this.user = user;
	}
}
