package com.ikai.photosharing.client.widgets;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.ikai.photosharing.client.events.GalleryUpdatedEvent;
import com.ikai.photosharing.client.events.GalleryUpdatedEventHandler;
import com.ikai.photosharing.client.services.UserImageService;
import com.ikai.photosharing.client.services.UserImageServiceAsync;
import com.ikai.photosharing.shared.LoginInfo;
import com.ikai.photosharing.shared.Tag;
import com.ikai.photosharing.shared.UploadedImage;
/**
 * 
 * This class represents the ImageOverlay that pops up when a User clicks on an
 * Image. It also provides listeners for management, tagging, and other
 * functions which are considered "Menu" type functions for a given image.
 * 
 * @author Ikai Lan
 * 
 */
public class ImageOverlay extends Composite implements HasHandlers {
  private static ImageOverlayUiBinder uiBinder = GWT
      .create(ImageOverlayUiBinder.class);
  UserImageServiceAsync imageService = GWT.create(UserImageService.class);
  private HandlerManager handlerManager;
  interface ImageOverlayUiBinder extends UiBinder<Widget, ImageOverlay> {
  }
  @UiField
  Button deleteButton;
  @UiField
  Image image;
  @UiField
  Label timestamp;
  @UiField
  VerticalPanel tagPanel;
  protected UploadedImage uploadedImage;
  LoginInfo loginInfo;
  public ImageOverlay(UploadedImage uploadedImage, LoginInfo loginInfo) {
    handlerManager = new HandlerManager(this);
    this.uploadedImage = uploadedImage;
    this.loginInfo = loginInfo;
    initWidget(uiBinder.createAndBindUi(this));
    image.setUrl(uploadedImage.getServingUrl());
    timestamp.setText("Created at:" + uploadedImage.getCreatedAt());
    if (loginInfo != null
        && (loginInfo.getId().equals(uploadedImage.getOwnerId()))) {
      deleteButton.setText("Delete image");
      deleteButton.setVisible(true);
    } else {
      deleteButton.setVisible(false);
    }
    // Now let's fetch the tags
    imageService.getTagsForImage(uploadedImage,
        new AsyncCallback<List<Tag>>() {
          @Override
          public void onFailure(Throwable caught) {
            // TODO Auto-generated method stub
          }
          @Override
          public void onSuccess(List<Tag> result) {
            // TODO Auto-generated method stub
            for (Tag tag : result) {
              tagPanel.add(new HTMLPanel(tag.getBody()));
            }
          }
        });
  }
  @UiHandler("image")
  void onClickImage(MouseDownEvent e) {
    Element imageElement = e.getRelativeElement();
    int x = e.getRelativeX(imageElement);
    int y = e.getRelativeY(imageElement);
    // Window.alert("X: " + x + " Y: "+ y);
    TagDialog tagDialog = new TagDialog(image, x, y);
    tagDialog.showAndFocus();
  }
  /**
   * 
   * Handles clicking of the delete button if owned.
   * 
   * @param {{@link ClickEvent} e
   */
  @UiHandler("deleteButton")
  void onClick(ClickEvent e) {
    final ImageOverlay overlay = this;
    imageService.deleteImage(uploadedImage.getKey(),
        new AsyncCallback<Void>() {
          @Override
          public void onSuccess(Void result) {
            GalleryUpdatedEvent event = new GalleryUpdatedEvent();
            fireEvent(event);
            overlay.removeFromParent();
          }
          @Override
          public void onFailure(Throwable caught) {
            // TODO Auto-generated method stub
          }
        });
  }
  /**
   * @author Ikai Lan
   * 
   *         This is the dialog box to ask the user to tag the image
   */
  private class TagDialog extends DialogBox {
    private TextBox textBox;
    public TagDialog(Image image, final int x, final int y) {
      // Set the dialog box's caption.
      setText("Tagging X: " + x + " Y: " + y);
      setAutoHideEnabled(true);
      int dialogX = image.getAbsoluteLeft() + x;
      int dialogY = image.getAbsoluteTop() + y;
      setPopupPosition(dialogX, dialogY);
      VerticalPanel tagPanel = new VerticalPanel();
      textBox = new TextBox();
      tagPanel.add(textBox);
      textBox.addKeyPressHandler(new KeyPressHandler() {
        @Override
        public void onKeyPress(KeyPressEvent event) {
          if (event.getCharCode() == KeyCodes.KEY_ENTER) {
            saveTag(x, y, textBox);
          }
        }
      });
      Button ok = new Button("Tag");
      ok.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
          saveTag(x, y, textBox);
        }
      });
      tagPanel.add(ok);
      setWidget(tagPanel);
    }
    public void showAndFocus() {
      show();
      textBox.setFocus(true);
    }
    private void saveTag(final int x, final int y, final TextBox textBox) {
      Tag tag = new Tag();
      // TODO: Change this to also pass the Image
      tag.setPhotoKey(uploadedImage.getKey());
      tag.setBody(textBox.getValue());
      tag.setX(x);
      tag.setY(y);
      imageService.tagImage(tag, new AsyncCallback<String>() {
        @Override
        public void onFailure(Throwable caught) {
          // TODO Auto-generated method stub
        }
        @Override
        public void onSuccess(String result) {
          TagDialog.this.hide();
        }
      });
    }
  }
  @Override
  public void fireEvent(GwtEvent<?> event) {
    handlerManager.fireEvent(event);
  }
  public HandlerRegistration addGalleryUpdatedEventHandler(
      GalleryUpdatedEventHandler handler) {
    return handlerManager.addHandler(GalleryUpdatedEvent.TYPE, handler);
  }
}