/*
 * 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.repeater;

import java.util.Iterator;

import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.OddEvenItem;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy;
import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;


/**
 * Page that demonstrates using RefreshingView in a form. The component reuses its items, to allow
 * adding or removing rows without necessarily validating the form, and preserving component state
 * which preserves error messages, etc.
 */
public class FormPage extends BasePage
{
	final Form<?> form;

	/**
	 * constructor
	 */
	public FormPage()
	{
		form = new Form("form");
		add(form);

		// create a repeater that will display the list of contacts.
		RefreshingView<Contact> refreshingView = new RefreshingView<Contact>("simple")
		{
			@Override
			protected Iterator<IModel<Contact>> getItemModels()
			{
				// for simplicity we only show the first 10 contacts
				SortParam<String> sort = new SortParam<>("firstName", true);
				Iterator<Contact> contacts = DatabaseLocator.getDatabase()
					.find(0, 10, sort)
					.iterator();

				// the iterator returns contact objects, but we need it to
				// return models, we use this handy adapter class to perform
				// on-the-fly conversion.
				return new ModelIteratorAdapter<Contact>(contacts)
				{

					@Override
					protected IModel<Contact> model(Contact object)
					{
						return new CompoundPropertyModel<>(
							new DetachableContactModel(object));
					}
				};
			}

			@Override
			protected void populateItem(final Item<Contact> item)
			{
				// populate the row of the repeater
				IModel<Contact> contact = item.getModel();
				item.add(new ActionPanel("actions", contact));
				item.add(new TextField<>("id"));
				item.add(new TextField<>("firstName"));
				item.add(new TextField<>("lastName"));
				item.add(new TextField<>("homePhone"));
				item.add(new TextField<>("cellPhone"));
			}

			@Override
			protected Item<Contact> newItem(String id, int index, IModel<Contact> model)
			{
				// this item sets markup class attribute to either 'odd' or
				// 'even' for decoration
				return new OddEvenItem<>(id, index, model);
			}
		};

		// because we are in a form we need to preserve state of the component
		// hierarchy (because it might contain things like form errors that
		// would be lost if the hierarchy for each item was recreated every
		// request by default), so we use an item reuse strategy.
		refreshingView.setItemReuseStrategy(ReuseIfModelsEqualStrategy.getInstance());


		form.add(refreshingView);
	}

	/**
	 * Panel that houses row-actions
	 */
	private class ActionPanel extends Panel
	{
		/**
		 * @param id
		 *            component id
		 * @param model
		 *            model for contact
		 */
		public ActionPanel(String id, IModel<Contact> model)
		{
			super(id, model);
			add(new Link<Void>("select")
			{
				@Override
				public void onClick()
				{
					setSelected((Contact)ActionPanel.this.getDefaultModelObject());
				}
			});

			SubmitLink removeLink = new SubmitLink("remove", form)
			{
				@Override
				public void onSubmit()
				{
					Contact contact = (Contact)ActionPanel.this.getDefaultModelObject();
					info("Removed contact " + contact);
					DatabaseLocator.getDatabase().delete(contact);
				}
			};
			removeLink.setDefaultFormProcessing(false);
			add(removeLink);
		}
	}
}
