package jp.sf.amateras.mirage.example.page;

import java.util.ArrayList;
import java.util.List;

import jp.sf.amateras.mirage.SqlManager;
import jp.sf.amateras.mirage.example.entity.Book;
import jp.sf.amateras.mirage.util.StringUtil;

import org.apache.click.ActionListener;
import org.apache.click.Context;
import org.apache.click.Control;
import org.apache.click.control.ActionLink;
import org.apache.click.control.Checkbox;
import org.apache.click.control.Column;
import org.apache.click.control.Decorator;
import org.apache.click.control.Form;
import org.apache.click.control.PageLink;
import org.apache.click.control.Submit;
import org.apache.click.control.TextField;
import org.apache.click.extras.control.FieldColumn;
import org.apache.click.extras.control.FormTable;
import org.apache.click.extras.control.IntegerField;
import org.apache.click.extras.control.PageSubmit;
import org.apache.click.util.ClickUtils;
import org.apache.click.util.HtmlStringBuffer;

public class BookListPage extends AbstractPage {

	private static final long serialVersionUID = 1L;

	protected FormTable table = new FormTable("table");
	protected PageLink edit = new PageLink("edit", getMessage("link.edit"), BookEditPage.class);
	protected ActionLink delete = new ActionLink("delete", getMessage("link.delete"));
	protected Submit batchDelete = new Submit("batchDelete", getMessage("button.batchDelete"));

	protected Form form = new Form("form");
	protected TextField keyword = new TextField("keyword", getMessage("label.keyword"), 40);
	protected IntegerField priceMin = new IntegerField("priceMin", getMessage("label.priceMin"));
	protected IntegerField priceMax = new IntegerField("priceMax", getMessage("label.priceMax"));
	protected PageSubmit register = new PageSubmit("register", getMessage("button.registerNewBook"), BookRegisterPage.class);
	protected Submit submit = new Submit("submit", getMessage("button.search"));
	protected Submit clear = new Submit("clear", getMessage("button.clear"));

	@Override
	public void onInit() {
		super.onInit();

		// Assembles search form
		form.setColumns(3);
		form.add(keyword);
		form.add(priceMin);
		form.add(priceMax);
		form.add(submit);
		form.add(clear);
		form.add(register);
		clear.setOnClick("clearForm()");
		addControl(form);

		// Assembles table
		table.setSortable(true);

		FieldColumn checkboxColumn = new FieldColumn("check", "", new Checkbox());
		table.addColumn(checkboxColumn);

		table.addColumn(new Column("id", getMessage("book.id")));
		table.addColumn(new Column("name", getMessage("book.name")));
		table.addColumn(new Column("author", getMessage("book.author")));
		table.addColumn(new Column("publisher", getMessage("book.publisher")));

		Column price = new Column("price", getMessage("book.price"));
		price.setDataStyle("text-align", "right");
		table.addColumn(price);

		Column publishDate = new Column("publishDate", getMessage("book.publishDate"));
		publishDate.setFormat("{0,date,yyyy/MM/dd}");
		table.addColumn(publishDate);

		Column image = new Column("imageName", getMessage("book.image"));
		image.setDecorator(new Decorator() {
			@Override
			public String render(Object object, Context context) {
				Book book = (Book) object;
				if(StringUtil.isEmpty(book.getImageName())){
					return "&nbsp;";
				} else {
					return String.format("<a href=\"%s/image?id=%d\">%s</a>",
							context.getServletContext().getContextPath(),
							book.getId(),
							getFormat().html(book.getImageName()));
				}
			}
		});
		table.addColumn(image);

		Column command = new Column("command", getMessage("book.command")){
			private static final long serialVersionUID = 1L;

			@Override
			protected void renderTableDataContent(Object row, HtmlStringBuffer buffer,
					Context context, int rowIndex) {

				edit.setParameter("id", ((Book) row).getId().toString());
				edit.render(buffer);

				buffer.append(" ");

				delete.setParameter("id", ((Book) row).getId().toString());
				delete.render(buffer);
			}
		};
		command.setSortable(false);
		table.addColumn(command);

		batchDelete.setActionListener(new ActionListener() {
			private static final long serialVersionUID = 1L;
			@Override
			public boolean onAction(Control source) {
				return doBatchDelete();
			}
		});
		table.getForm().add(batchDelete);

		table.setClass("blue1");
		table.setPageSize(10);

		delete.setAttribute("onclick",
				String.format("return confirm('%s');", getMessage("message.deleteConfirm")));
		delete.setActionListener(new ActionListener() {
			private static final long serialVersionUID = 1L;
			@Override
			public boolean onAction(Control source) {
				return doDelete();
			}
		});

		addControl(table);
		addControl(register);
		addControl(delete);
		addModel("title", getMessage("title.bookList"));

		setTableRows();
	}

	protected boolean doBatchDelete(){
		@SuppressWarnings("unchecked")
		List<Book> rowList = table.getRowList();
		List<Book> deleteList = new ArrayList<Book>();

		for(Book book: rowList){
			if(book.isCheck()){
				deleteList.add(book);
			}
		}

		if(!deleteList.isEmpty()){
			SqlManager sqlManager = getSqlManager();
			sqlManager.deleteBatch(deleteList);
		}

		setRedirect(BookListPage.class);
		return false;
	}

	protected boolean doDelete(){
		Book book = new Book();
		book.setId(new Long(delete.getParameter("id")));

		SqlManager sqlManager = getSqlManager();
		sqlManager.deleteEntity(book);

		setRedirect(BookListPage.class);
		return false;
	}

	private void setTableRows(){
		BookSearchParam param = (BookSearchParam)
		getContext().getSessionAttribute(BookSearchParam.class.getName());

		if(param == null){
			param = new BookSearchParam();
			getContext().setSessionAttribute(BookSearchParam.class.getName(), param);
		}

		ClickUtils.bind(form);

		if(submit.isClicked() || clear.isClicked()){
			form.copyTo(param);
		} else {
			form.copyFrom(param);
		}

		SqlManager sqlManager = getSqlManager();
		List<Book> bookList = sqlManager.getResultList(
				Book.class, SQL_PREFIX + "BookListPage_selectBooks.sql", param);

		table.setRowList(bookList);
	}

	public static class BookSearchParam {

		private String keyword;
		private Integer priceMin;
		private Integer priceMax;

		public String getSearchWord(){
			if(keyword == null){
				return null;
			}
			return "%" + keyword + "%";
		}

		public String getKeyword() {
			return keyword;
		}
		public void setKeyword(String keyword) {
			this.keyword = keyword;
		}
		public Integer getPriceMin() {
			return priceMin;
		}
		public void setPriceMin(Integer priceMin) {
			this.priceMin = priceMin;
		}
		public Integer getPriceMax() {
			return priceMax;
		}
		public void setPriceMax(Integer priceMax) {
			this.priceMax = priceMax;
		}
	}

}
