/*
 * Copyright 2010 Google Inc.
 * 
 * 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 com.google.gwt.examples.cell;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;

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

/**
 * Example of creating an editable {@link Cell}. This example creates a cell
 * that displays a Contact with a checkbox that indicates whether the contact is
 * a favorite or not.
 */
public class EditableCellExample implements EntryPoint {

  /**
   * A simple data type that represents a contact.
   */
  private static class Contact {
    private final String address;
    private final String name;

    public Contact(String name, String address) {
      this.name = name;
      this.address = address;
    }
  }

  /**
   * A custom {@link Cell} used to render a {@link Contact}. We extend
   * {@link AbstractCell} because it provides reasonable implementations of
   * methods that work for most use cases.
   */
  private class ContactCell extends AbstractCell<Contact> {

    public ContactCell() {
      // Our cell responds to change events and keydown events.
      super("change", "keydown");
    }

    @Override
    public void onBrowserEvent(Element parent, Contact value, Object key,
        NativeEvent event, ValueUpdater<Contact> valueUpdater) {
      // Check that the value is not null.
      if (value == null) {
        return;
      }

      // Call the super handler, which handlers the enter key.
      super.onBrowserEvent(parent, value, key, event, valueUpdater);

      // Handle click events.
      if ("change".equals(event.getType())) {
        updateFavorites(parent, value);
        showCurrentFavorites();
      }
    }

    @Override
    public void render(Contact value, Object key, SafeHtmlBuilder sb) {
      /*
       * Always do a null check on the value. Cell widgets can pass null to
       * cells if the underlying data contains a null, or if the data arrives
       * out of order.
       */
      if (value == null) {
        return;
      }

      // Add a checkbox. If the contact is a favorite, the box will be checked.
      sb.appendHtmlConstant("<table><tr><td valign=\"top\">");
      if (favorites.contains(value)) {
        sb.appendHtmlConstant("<input type=\"checkbox\" checked=checked/>");
      } else {
        sb.appendHtmlConstant("<input type=\"checkbox\" />");
      }
      sb.appendHtmlConstant("</td><td>");

      // Display the name in big letters.
      sb.appendHtmlConstant("<div style=\"size:200%;font-weight:bold;\">");
      sb.appendEscaped(value.name);
      sb.appendHtmlConstant("</div>");

      // Display the address in normal text.
      sb.appendHtmlConstant("<div style=\"padding-left:10px;\">");
      sb.appendEscaped(value.address);
      sb.appendHtmlConstant("</div>");

      sb.appendHtmlConstant("</td></tr></table>");
    }

    /**
     * By convention, cells that respond to user events should handle the enter
     * key. This provides a consistent user experience when users use keyboard
     * navigation in the widget. Our cell will toggle the checkbox on Enter.
     */
    @Override
    protected void onEnterKeyDown(Element parent, Contact value, Object key,
        NativeEvent event, ValueUpdater<Contact> valueUpdater) {
      // Toggle the checkbox.
      InputElement input = getInputElement(parent);
      input.setChecked(!input.isChecked());

      // Update the favorites based on the new state.
      updateFavorites(parent, value);

      // Show the new list of favorites.
      showCurrentFavorites();
    }

    /**
     * Get the checkbox input element from the parent element that wraps our
     * cell.
     * 
     * @param parent the parent element
     * @return the checkbox
     */
    private InputElement getInputElement(Element parent) {
      // We need to navigate down to our input element.
      TableElement table = parent.getFirstChildElement().cast();
      TableRowElement tr = table.getRows().getItem(0);
      TableCellElement td = tr.getCells().getItem(0);
      InputElement input = td.getFirstChildElement().cast();
      return input;
    }

    /**
     * Update the favorites list based on the state of the input element.
     */
    private void updateFavorites(Element parent, Contact value) {
      // Get the input element.
      InputElement input = getInputElement(parent);

      // Update the favorites based on the checked state.
      if (input.isChecked()) {
        favorites.add(value);
      } else {
        favorites.remove(value);
      }
    }
  }

  /**
   * The list of data to display.
   */
  private static final List<Contact> CONTACTS = Arrays.asList(new Contact(
      "John", "123 Fourth Avenue"), new Contact("Joe", "22 Lance Ln"),
      new Contact("Michael", "1283 Berry Blvd"), new Contact("Sarah",
          "100 Hundred St."), new Contact("George", "1600 Pennsylvania Avenue"));

  /**
   * Our list of favorite contacts.
   */
  private final List<Contact> favorites = new ArrayList<EditableCellExample.Contact>();

  public void onModuleLoad() {
    // Create a cell to render each value.
    ContactCell contactCell = new ContactCell();

    // Use the cell in a CellList.
    CellList<Contact> cellList = new CellList<Contact>(contactCell);

    // Push the data into the widget.
    cellList.setRowData(0, CONTACTS);

    // Add it to the root panel.
    RootPanel.get().add(cellList);
  }

  /**
   * Show the list of favorites.
   */
  private void showCurrentFavorites() {
    if (favorites.size() > 0) {
      String text = "You favorite contacts are ";
      boolean first = true;
      for (Contact contact : favorites) {
        if (!first) {
          text += ", ";
        } else {
          first = false;
        }
        text += contact.name;
      }
      Window.alert(text);
    } else {
      Window.alert("You have not selected any favorites.");
    }
  }
}