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

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant;

import java.util.Set;

/**
 * A {@link Cell} decorator that adds an icon to another {@link Cell}.
 *
 * <p>
 * Note: This class is new and its interface subject to change.
 * </p>
 *
 * @param <C> the type that this Cell represents
 */
public class IconCellDecorator<C> implements Cell<C> {

  private final Cell<C> cell;
  private final String iconHtml;
  private final int imageWidth;
  private final String placeHolderHtml;

  /**
   * Construct a new {@link IconCellDecorator}. The icon and the content will be
   * middle aligned by default.
   *
   * @param icon the icon to use
   * @param cell the cell to decorate
   */
  public IconCellDecorator(ImageResource icon, Cell<C> cell) {
    this(icon, cell, HasVerticalAlignment.ALIGN_MIDDLE, 6);
  }

  /**
   * Construct a new {@link IconCellDecorator}.
   *
   * @param icon the icon to use
   * @param cell the cell to decorate
   * @param valign the vertical alignment attribute of the contents
   * @param spacing the pixel space between the icon and the cell
   */
  public IconCellDecorator(ImageResource icon, Cell<C> cell,
      VerticalAlignmentConstant valign, int spacing) {
    this.cell = cell;
    this.iconHtml = getImageHtml(icon, valign, false);
    this.imageWidth = icon.getWidth() + 6;
    this.placeHolderHtml = getImageHtml(icon, valign, true);
  }

  public boolean dependsOnSelection() {
    return cell.dependsOnSelection();
  }

  public Set<String> getConsumedEvents() {
    return cell.getConsumedEvents();
  }

  public boolean handlesSelection() {
    return cell.handlesSelection();
  }
  
  public boolean isEditing(Element element, C value, Object key) {
    return cell.isEditing(element, value, key);
  }

  public void onBrowserEvent(Element parent, C value, Object key,
      NativeEvent event, ValueUpdater<C> valueUpdater) {
    cell.onBrowserEvent(getCellParent(parent), value, key, event, valueUpdater);
  }

  public void render(C value, Object key, StringBuilder sb) {
    sb.append("<div style='position:relative;padding-left:");
    sb.append(imageWidth);
    sb.append("px;'>");
    if (isIconUsed(value)) {
      sb.append(getIconHtml(value));
    } else {
      sb.append(placeHolderHtml);
    }
    sb.append("<div>");
    cell.render(value, key, sb);
    sb.append("</div></div>");
  }

  public void setValue(Element parent, C value, Object key) {
    cell.setValue(getCellParent(parent), value, key);
  }

  /**
   * Get the HTML string that represents the icon. Override this method to
   * change the icon based on the value.
   *
   * @param value the value being rendered
   * @return the HTML string that represents the icon
   */
  protected String getIconHtml(C value) {
    return iconHtml;
  }

  /**
   * Check if the icon should be used for the value. If the icon should not be
   * used, a placeholder of the same size will be used instead. The default
   * implementations returns true.
   *
   * @param value the value being rendered
   * @return true to use the icon, false to use a placeholder
   */
  protected boolean isIconUsed(C value) {
    return true;
  }

  /**
   * Get the HTML representation of an image. Visible for testing.
   *
   * @param res the {@link ImageResource} to render as HTML
   * @param valign the vertical alignment
   * @param isPlaceholder if true, do not include the background image
   * @return the rendered HTML
   */
  // TODO(jlabanca): Move this to a Utility class.
  String getImageHtml(ImageResource res, VerticalAlignmentConstant valign,
      boolean isPlaceholder) {
    // Add the position and dimensions.
    StringBuilder sb = new StringBuilder();
    sb.append("<div style=\"position:absolute;left:0px;top:0px;height:100%;");
    sb.append("width:").append(res.getWidth()).append("px;");

    // Add the background, vertically centered.
    if (!isPlaceholder) {
      String vert = valign == HasVerticalAlignment.ALIGN_MIDDLE
          ? "center" : valign.getVerticalAlignString();
      sb.append("background:url('").append(res.getURL()).append("') ");
      sb.append("no-repeat scroll ").append(vert).append(
          " center transparent;");
    }

    // Close the div and return.
    sb.append("\"></div>");
    return sb.toString();
  }

  /**
   * Get the parent element of the decorated cell.
   *
   * @param parent the parent of this cell
   * @return the decorated cell's parent
   */
  private Element getCellParent(Element parent) {
    return parent.getFirstChildElement().getChild(1).cast();
  }
}
