// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.client;

import java.util.Date;
import java.util.List;

import com.google.appinventor.client.explorer.youngandroid.GalleryImages;
import com.google.appinventor.client.explorer.youngandroid.GalleryPage;
import com.google.appinventor.shared.rpc.project.GalleryApp;
import com.google.appinventor.shared.rpc.project.GalleryComment;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabPanel;

public class GalleryGuiFactory {
  GalleryClient gallery = GalleryClient.getInstance();

  public static final OdeMessages MESSAGES = Ode.getMessages();

  private static final String PERSON_URL = "/static/images/person.png";
  private static final String RED_HEART_ICON_URL = "/static/images/numLike.png";
  private static final String HOLLOW_HEART_ICON_URL = "/static/images/numLikeHollow.png";
  private static final String DOWNLOAD_ICON_URL = "/static/images/numDownload.png";
  private static final String NUM_VIEW_ICON_URL = "/static/images/numView.png";
  private static final String NUM_COMMENT_ICON_URL = "/static/images/numComment.png";

  /**
   * Generates a new GalleryGuiFactory instance.
   */
  public GalleryGuiFactory() {
  }

  /**
   * Class representing the GUI of a single gallery app.
   */
  private class GalleryAppWidget {
    final Label nameLabel;
    final Label authorLabel;
    final Label numDownloadsLabel;
    final Label numCommentsLabel;
    final Label numViewsLabel;
    final Label numLikesLabel;
    final Image image;

    private GalleryAppWidget(final GalleryApp app) {
      nameLabel = new Label(app.getTitle());
      authorLabel = new Label(app.getDeveloperName());
      numDownloadsLabel = new Label(Integer.toString(app.getDownloads()));
      numLikesLabel = new Label(Integer.toString(app.getLikes()));
      numViewsLabel = new Label(Integer.toString(app.getViews()));
      numCommentsLabel = new Label(Integer.toString(app.getComments()));
      image = new Image();
      image.addErrorHandler(new ErrorHandler() {
        public void onError(ErrorEvent event) {
          image.setResource(GalleryImages.get().genericApp());
        }
      });
      String url = gallery.getCloudImageURL(app.getGalleryAppId());
      image.setUrl(url);

      if(gallery.getSystemEnvironment() != null &&
          gallery.getSystemEnvironment().equals("Development")){
        final OdeAsyncCallback<String> callback = new OdeAsyncCallback<String>(
          // failure message
          MESSAGES.galleryError()) {
            @Override
            public void onSuccess(String newUrl) {
              if (newUrl != null) {
                image.setUrl(newUrl + "?" + System.currentTimeMillis());
              }
            }
          };
        Ode.getInstance().getGalleryService().getBlobServingUrl(url, callback);
      }
    }
  }

  /**
   * Loads the proper tab GUI with gallery's app data.
   * @param apps: list of returned gallery apps from callback.
   * @param container: the GUI panel where apps will reside.
   * @param refreshable: if true then the GUI can be reloaded later.
   */
  public void generateHorizontalAppList(List<GalleryApp> apps,
      FlowPanel container, Boolean refreshable) {
    if (refreshable) {
      // Flush the panel's content if we knew new stuff is coming in!
      container.clear();
    }
    for (final GalleryApp app : apps) {
      // Create the associated GUI object for app
      GalleryAppWidget gaw = new GalleryAppWidget(app);

      // Create necessary GUI wrappers and components
      FlowPanel appCard = new FlowPanel();
      FlowPanel appCardContent = new FlowPanel();
      FlowPanel appCardMeta = new FlowPanel();

      // Special processing for the app title, mainly for fade-out effect
      HTML appTitle = new HTML("" +
        "<div class='gallery-title'>" + gaw.nameLabel.getText() +
        "<span class='paragraph-end-block'></span></div>");

      // Special processing for the app author, mainly for fade-out effect
      HTML appAuthor = new HTML("" +
        "<div class='gallery-subtitle'>" + gaw.authorLabel.getText() +
        "<span class='paragraph-end-block'></span></div>");

      gaw.image.addClickHandler(new ClickHandler() {
      //  @Override
        public void onClick(ClickEvent event) {
          Ode.getInstance().switchToGalleryAppView(app, GalleryPage.VIEWAPP);
        }
      });

      appTitle.addClickHandler(new ClickHandler() {
      //  @Override
        public void onClick(ClickEvent event) {
          Ode.getInstance().switchToGalleryAppView(app, GalleryPage.VIEWAPP);
        }
      });

      // Add everything to the top-level stuff
      appCard.add(gaw.image);
      appCard.add(appCardContent);
      appCardContent.add(appTitle);
      appCardContent.add(appAuthor);
      appCardContent.add(appCardMeta);

      // Set helper icons
      Image numViews = new Image();
      numViews.setUrl(NUM_VIEW_ICON_URL);
      Image numDownloads = new Image();
      numDownloads.setUrl(DOWNLOAD_ICON_URL);
      Image numLikes = new Image();
      numLikes.setUrl(HOLLOW_HEART_ICON_URL);
    // For generic cards, do not show comment
//    Image numComments = new Image();
//    numComments.setUrl(NUM_COMMENT_ICON_URL);

//      appCardMeta.add(numViews);
//      appCardMeta.add(gaw.numViewsLabel);
      appCardMeta.add(numDownloads);
      appCardMeta.add(gaw.numDownloadsLabel);
      appCardMeta.add(numLikes);
      appCardMeta.add(gaw.numLikesLabel);
      // For generic cards, do not show comment
//      appCardMeta.add(numComments);
//      appCardMeta.add(gaw.numCommentsLabel);

      // Add associated styling
      appCard.addStyleName("gallery-card");
      gaw.image.addStyleName("gallery-card-cover");
//      gaw.nameLabel.addStyleName("gallery-title");
//      gaw.authorLabel.addStyleName("gallery-subtitle");
      appCardContent.addStyleName("gallery-card-content");
      gaw.numViewsLabel.addStyleName("gallery-meta");
      gaw.numDownloadsLabel.addStyleName("gallery-meta");
      gaw.numLikesLabel.addStyleName("gallery-meta");
//      gaw.numCommentsLabel.addStyleName("gallery-meta");

      container.add(appCard);
    }
    container.addStyleName("gallery-app-collection");
    container.addStyleName("clearfix"); /* For redesigned navigation buttons */

  }

  /**
   * Creates list of comments in the app page.
   * @param comments: list of returned gallery comments from callback.
   * @param container: the GUI panel where comments will reside.
   */
  public void generateAppPageComments(List<GalleryComment> comments, FlowPanel container) {
    container.clear();  // so don't show previous listing
    if (comments == null) {
      Label noComments = new Label("This app does not have any comments yet.");
      noComments.addStyleName("comment-nope");
      container.add(noComments);
      return;
    }

    for ( GalleryComment c : comments) {
      FlowPanel commentItem = new FlowPanel();
      FlowPanel commentPerson = new FlowPanel();
      FlowPanel commentMeta = new FlowPanel();
      FlowPanel commentContent = new FlowPanel();

      // Add commentPerson, default avatar for now
      Image cPerson = new Image();
      cPerson.setUrl(PERSON_URL);
      commentPerson.add(cPerson);
      commentPerson.addStyleName("comment-person");
      commentItem.add(commentPerson);

      // Add commentContent
      Label cAuthor = new Label(c.getUserName());
      cAuthor.addStyleName("comment-author");
      commentMeta.add(cAuthor);

      Date commentDate = new Date(c.getTimeStamp());
      DateTimeFormat dateFormat = DateTimeFormat.getFormat("yyyy/MM/dd hh:mm:ss a");
      Label cDate = new Label(" on " + dateFormat.format(commentDate));
      cDate.addStyleName("comment-date");
      commentMeta.add(cDate);

      commentMeta.addStyleName("comment-meta");
      commentContent.add(commentMeta);

      Label cText = new Label(c.getComment());
      cText.addStyleName("comment-text");
      commentContent.add(cText);

      commentContent.addStyleName("comment-content");
      commentItem.add(commentContent);

      commentItem.addStyleName("comment-item");
      commentItem.addStyleName("clearfix");
      container.add(commentItem);
    }
  }

  /**
   * Creates a sidebar showcasing apps; the CSS name will be the same as the
   * passed-in container's name. This sidebar shows up as a tab under parent.
   *
   * @param apps: list of returned gallery apps from callback.
   *
   * @param parent: the parent TabPanel that this panel will reside in.
   *
   * @param container: the panel containing this particular sidebar.
   *
   * @param name: the name or title of this particular sidebar.
   *
   * @param desc: the short description of this particular sidebar.
   *
   * @param refreshable: if true then this sidebar can be reloaded later.
   *
   * @param isDefault: if true then this sidebar is the default tab showing.
   */
  public void generateSidebar(List<GalleryApp> apps, TabPanel parent,
      FlowPanel container, String name, String desc,
      Boolean refreshable, Boolean isDefault) {
    if (refreshable) {
      // Flush the panel's content if we knew new stuff is coming in!
      container.clear();
    }
    parent.add(container, name);
    if (isDefault) {
      parent.selectTab(0);  //TODO: fix order
    }

    Label descLabel = new Label(desc);
    descLabel.addStyleName("gallery-showcase-desc");
    container.add(descLabel);

    for (final GalleryApp app : apps) {
      // Create the associated GUI object for app
      GalleryAppWidget gaw = new GalleryAppWidget(app);

      // Create necessary GUI wrappers and components
      FlowPanel appCard = new FlowPanel();
      FlowPanel appCardContent = new FlowPanel();
      FlowPanel appCardMeta = new FlowPanel();

      // Special processing for the app title, mainly for fade-out effect
      HTML appTitle = new HTML("" +
        "<div class='gallery-title'>" + gaw.nameLabel.getText() +
        "<span class='paragraph-end-block'></span></div>");

      // Special processing for the app author, mainly for fade-out effect
      HTML appAuthor = new HTML("" +
        "<div class='gallery-subtitle'>" + gaw.authorLabel.getText() +
        "<span class='paragraph-end-block'></span></div>");

      gaw.image.addClickHandler(new ClickHandler() {
      //  @Override
        public void onClick(ClickEvent event) {
          Ode.getInstance().switchToGalleryAppView(app, GalleryPage.VIEWAPP);
        }
      });

      appTitle.addClickHandler(new ClickHandler() {
      //  @Override
        public void onClick(ClickEvent event) {
          Ode.getInstance().switchToGalleryAppView(app, GalleryPage.VIEWAPP);
        }
      });

      // Add everything to the top-level stuff
      appCard.add(gaw.image);
      appCard.add(appCardContent);
      appCardContent.add(appTitle);
      appCardContent.add(appAuthor);
      appCardContent.add(appCardMeta);

      // Set helper icons
//      Image numViews = new Image();
//      numViews.setUrl(NUM_VIEW_ICON_URL);
      Image numDownloads = new Image();
      numDownloads.setUrl(DOWNLOAD_ICON_URL);
      Image numLikes = new Image();
      numLikes.setUrl(HOLLOW_HEART_ICON_URL);
    // For generic cards, do not show comment
//    Image numComments = new Image();
//    numComments.setUrl(NUM_COMMENT_ICON_URL);

//      appCardMeta.add(numViews);
//      appCardMeta.add(gaw.numViewsLabel);
      appCardMeta.add(numDownloads);
      appCardMeta.add(gaw.numDownloadsLabel);
      appCardMeta.add(numLikes);
      appCardMeta.add(gaw.numLikesLabel);
      // For generic cards, do not show comment
//      appCardMeta.add(numComments);
//      appCardMeta.add(gaw.numCommentsLabel);

      // Add associated styling
      appCard.addStyleName("gallery-card");
      appCard.addStyleName("clearfix");
      gaw.image.addStyleName("gallery-card-cover");
//      gaw.nameLabel.addStyleName("gallery-title");
//      gaw.authorLabel.addStyleName("gallery-subtitle");
      appCardContent.addStyleName("gallery-card-content");
      gaw.numViewsLabel.addStyleName("gallery-meta");
      gaw.numDownloadsLabel.addStyleName("gallery-meta");
      gaw.numLikesLabel.addStyleName("gallery-meta");
//      gaw.numCommentsLabel.addStyleName("gallery-meta");

      container.add(appCard);
    }

  }
}