/*
 * 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.sample.showcase.client.content.cell;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.CompositeCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.HasCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.sample.showcase.client.content.cell.ContactDatabase.Category;
import com.google.gwt.sample.showcase.client.content.cell.ContactDatabase.ContactInfo;
import com.google.gwt.sample.showcase.client.content.cell.CwCellList.ContactCell;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.TreeViewModel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * The {@link TreeViewModel} used to organize contacts into a hierarchy.
 */
public class ContactTreeViewModel implements TreeViewModel {

  /**
   * The images used for this example.
   */
  static interface Images extends ClientBundle {
    ImageResource contact();

    ImageResource contactsGroup();
  }

  /**
   * The cell used to render categories.
   */
  private static class CategoryCell extends AbstractCell<Category> {

    /**
     * The html of the image used for contacts.
     */
    private final String imageHtml;

    public CategoryCell(ImageResource image) {
      this.imageHtml = AbstractImagePrototype.create(image).getHTML();
    }

    @Override
    public void render(Category value, Object key, SafeHtmlBuilder sb) {
      if (value != null) {
        sb.appendHtmlConstant(imageHtml).appendEscaped(" ");
        sb.appendEscaped(value.getDisplayName());
      }
    }
  }

  /**
   * Tracks the number of contacts in a category that begin with the same
   * letter.
   */
  private static class LetterCount implements Comparable<LetterCount> {
    private final Category category;
    private final char firstLetter;
    private int count;

    /**
     * Construct a new {@link LetterCount} for one contact.
     *
     * @param category the category
     * @param firstLetter the first letter of the contacts name
     */
    public LetterCount(Category category, char firstLetter) {
      this.category = category;
      this.firstLetter = firstLetter;
      this.count = 1;
    }

    public int compareTo(LetterCount o) {
      return (o == null) ? -1 : (firstLetter - o.firstLetter);
    }

    @Override
    public boolean equals(Object o) {
      return compareTo((LetterCount) o) == 0;
    }

    @Override
    public int hashCode() {
      return firstLetter;
    }

    /**
     * Increment the count.
     */
    public void increment() {
      count++;
    }
  }

  /**
   * A Cell used to render the LetterCount.
   */
  private static class LetterCountCell extends AbstractCell<LetterCount> {

    @Override
    public void render(LetterCount value, Object key, SafeHtmlBuilder sb) {
      if (value != null) {
        sb.appendEscaped(value.firstLetter + " (" + value.count + ")");
      }
    }
  }

  /**
   * The static images used in this model.
   */
  private static Images images;

  private final ListDataProvider<Category> categoryDataProvider;
  private final Cell<ContactInfo> contactCell;
  private final SelectionModel<ContactInfo> selectionModel;

  public ContactTreeViewModel(
      final SelectionModel<ContactInfo> selectionModel) {
    this.selectionModel = selectionModel;
    if (images == null) {
      images = GWT.create(Images.class);
    }

    // Create a data provider that provides categories.
    categoryDataProvider = new ListDataProvider<Category>();
    List<Category> categoryList = categoryDataProvider.getList();
    for (Category category : ContactDatabase.get().queryCategories()) {
      categoryList.add(category);
    }

    // Construct a composite cell for contacts that includes a checkbox.
    List<HasCell<ContactInfo, ?>> hasCells = new ArrayList<
        HasCell<ContactInfo, ?>>();
    hasCells.add(new HasCell<ContactInfo, Boolean>() {

      private CheckboxCell cell = new CheckboxCell(true);

      public Cell<Boolean> getCell() {
        return cell;
      }

      public FieldUpdater<ContactInfo, Boolean> getFieldUpdater() {
        return new FieldUpdater<ContactInfo, Boolean>() {
          public void update(int index, ContactInfo object, Boolean value) {
            selectionModel.setSelected(object, value);
          }
        };
      }

      public Boolean getValue(ContactInfo object) {
        return selectionModel.isSelected(object);
      }
    });
    hasCells.add(new HasCell<ContactInfo, ContactInfo>() {

      private ContactCell cell = new ContactCell(images.contact());

      public Cell<ContactInfo> getCell() {
        return cell;
      }

      public FieldUpdater<ContactInfo, ContactInfo> getFieldUpdater() {
        return null;
      }

      public ContactInfo getValue(ContactInfo object) {
        return object;
      }
    });
    contactCell = new CompositeCell<ContactInfo>(hasCells) {
      @Override
      public void onBrowserEvent(Element parent, ContactInfo value, Object key,
          NativeEvent event, ValueUpdater<ContactInfo> valueUpdater) {
        // Make sure that the composition cells see the event.
        super.onBrowserEvent(parent, value, key, event, valueUpdater);

        if ("keyup".equals(event.getType())
            && event.getKeyCode() == KeyCodes.KEY_ENTER) {
          selectionModel.setSelected(value, !selectionModel.isSelected(value));
        }
      }

      @Override
      public void render(ContactInfo value, Object key, SafeHtmlBuilder sb) {
        sb.appendHtmlConstant("<table><tbody><tr>");
        super.render(value, key, sb);
        sb.appendHtmlConstant("</tr></tbody></table>");
      }

      @Override
      protected Element getContainerElement(Element parent) {
        // Return the first TR element in the table.
        return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
      }

      @Override
      protected <X> void render(ContactInfo value, Object key, SafeHtmlBuilder sb,
          HasCell<ContactInfo, X> hasCell) {
        Cell<X> cell = hasCell.getCell();
        sb.appendHtmlConstant("<td>");
        cell.render(hasCell.getValue(value), key, sb);
        sb.appendHtmlConstant("</td>");
      }
    };
  }

  public <T> NodeInfo<?> getNodeInfo(T value) {
    if (value == null) {
      // Return top level categories.
      return new DefaultNodeInfo<Category>(
          categoryDataProvider, new CategoryCell(images.contactsGroup()));
    } else if (value instanceof Category) {
      // Return the first letters of each first name.
      Category category = (Category) value;
          List<ContactInfo> contacts = ContactDatabase.get().queryContactsByCategory(category);
      Map<Character, LetterCount> counts = new TreeMap<
          Character, LetterCount>();
      for (ContactInfo contact : contacts) {
        Character first = contact.getFirstName().charAt(0);
        LetterCount count = counts.get(first);
        if (count == null) {
          count = new LetterCount(category, first);
          counts.put(first, count);
        } else {
          count.increment();
        }
      }
      List<LetterCount> orderedCounts = new ArrayList<LetterCount>(
          counts.values());
      return new DefaultNodeInfo<LetterCount>(
          new ListDataProvider<LetterCount>(orderedCounts),
          new LetterCountCell());
    } else if (value instanceof LetterCount) {
      // Return the contacts with the specified character and first name.
      LetterCount count = (LetterCount) value;
          List<ContactInfo> contacts =
            ContactDatabase.get().queryContactsByCategoryAndFirstName(count.category,
                count.firstLetter + "");
      ListDataProvider<ContactInfo> dataProvider = new ListDataProvider<
          ContactInfo>(contacts, ContactInfo.KEY_PROVIDER);
      return new DefaultNodeInfo<ContactInfo>(
          dataProvider, contactCell, selectionModel, null);
    }

    // Unhandled type.
    String type = value.getClass().getName();
    throw new IllegalArgumentException("Unsupported object type: " + type);
  }

  public boolean isLeaf(Object value) {
    return value instanceof ContactInfo;
  }
}
