package com.loquake.web.client;

import java.util.List;

import com.google.code.gwt.geolocation.client.Coordinates;
import com.google.code.gwt.geolocation.client.Geolocation;
import com.google.code.gwt.geolocation.client.Position;
import com.google.code.gwt.geolocation.client.PositionCallback;
import com.google.code.gwt.geolocation.client.PositionError;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.loquake.web.client.dao.EarthquakeService;
import com.loquake.web.client.dao.EarthquakeServiceAsync;
import com.loquake.web.client.model.EQResult;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Loquake2 implements EntryPoint {
  /**
   * The message displayed to the user when the server cannot be reached or
   * returns an error.
   */
  private static final String SERVER_ERROR = "An error occurred while "
      + "attempting to contact the server. Please check your network " + "connection and try again.";

  /**
   * Create a remote service proxy to talk to the server-side Greeting service.
   */
  private final EarthquakeServiceAsync earthquakeService = GWT.create(EarthquakeService.class);
  private final EarthquakeWidget quakes = new EarthquakeWidget();
  private final VerticalPanel messagePanel = new VerticalPanel();
  private final Label messages = new Label();
  private int c = 0;

  /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
    final VerticalPanel main = new VerticalPanel();
    main.add(quakes);

    messagePanel.setSpacing(4);
    messagePanel.add(messages);
    messages.setStylePrimaryName("messages");
    RootPanel.get("messages").add(messagePanel);
    
    
    final VerticalPanel doc = new VerticalPanel();
    doc.add(main);
    
    RootPanel.get("main").add(doc);
    
    final Anchor about = new Anchor();
    about.setText("about");
    about.setHref("http://www.representqueens.com/lq2/about.html");
    doc.add(about);
    doc.setCellHorizontalAlignment(about, HasHorizontalAlignment.ALIGN_RIGHT);
    doloc();
  }
  
  private void gotLocation(final VerticalPanel main, final Position position) {
    // 37.7736058f, -122.4272572f
    final float lat = (float) position.getCoords().getLatitude();
    final float lon = (float) position.getCoords().getLongitude();
    gotLocation(lat, lon);
  }
  
  private void gotLocation(final float lat, final float lon) {
    // 37.7736058f, -122.4272572f
    
    messagePanel.clear();
    final Label l = new Label("location: " + lat + ", " + lon);
    messagePanel.add(l);
    messagePanel.setCellHorizontalAlignment(l, HasHorizontalAlignment.ALIGN_RIGHT);

    
    earthquakeService.getLatestForLocation(lat, lon, 10, new AsyncCallback<List<EQResult>>() {
      public void onFailure(Throwable caught) {
      }
      public void onSuccess(List<EQResult> result) {
        if (result.isEmpty()) {
          noQuakes();
        } else {
          quakes.setEarthquakes(result);
        }
      }
    });
  }
  
  private void noQuakes() {
    String explain = "No earthquakes found within 100 miles of where you are!<br>";
    explain += "<p>Well, you can continue using a demo latitude and longitude from San Francisco.</p>";
    
    messagePanel.add(new HTML(explain));
    
    final Anchor a = new Anchor("Ok, I'll pretend I'm in San Francisco.");
    a.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        gotLocation(37.7736058f, -122.4272572f);
      }
    });
    
    messagePanel.add(a);
  }
  
  
  private void addFailureExplain() {
    String explain = "loquake requires geolocation features of HTML 5, which is not supported by your browser.<br>";
    explain += "Please upgrade to <a href='http://www.getfirefox.com' target='_blank'>Firefox 3.5</a> in order to use this site.<br>";
    explain += "<p>Alternatively, you can continue using a demo latitude and longitude from San Francisco.</p>";
    
    messagePanel.add(new HTML(explain));
    
    final Anchor a = new Anchor("Ok, I'll pretend I'm in San Francisco.");
    a.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        gotLocation(37.7736058f, -122.4272572f);
      }
    });
    
    messagePanel.add(a);
  }
  
  private void doloc() {
    messages.setText("Obtaining Geolocation....");
    if (!Geolocation.isSupported()) {
      messages.setText("Obtaining Geolocation... FAILED! Geolocation API is not supported.");
      addFailureExplain();
      return;
    }
    Geolocation geo = Geolocation.getGeolocation();
    if (geo == null) {
      messages.setText("Obtaining Geolocation... FAILED! Object is null.");
      addFailureExplain();
      return;
    }
    messages.setText("Obtaining Geolocation... DONE!");
    messages.setText("Finding position...");

    geo.getCurrentPosition(new PositionCallback() {
      public void onFailure(PositionError error) {
        String message = "";
        switch (error.getCode()) {
          case PositionError.UNKNOWN_ERROR:
            message = "Unknown Error";
            break;
          case PositionError.PERMISSION_DENIED:
            message = "Permission Denied";
            break;
          case PositionError.POSITION_UNAVAILABLE:
            message = "Position Unavailable";
            break;
          case PositionError.TIMEOUT:
            message = "Time-out";
            break;
          default:
            message = "Unknown error code.";
        }
        messages.setText("Obtaining position... FAILED! Message: '"
            + error.getMessage() + "', code: " + error.getCode() + " ("
            + message + ")");
        
        addFailureExplain();
      }

      public void onSuccess(Position position) {
        Coordinates c = position.getCoords();
        messages.setText("Found position: " + c.getLatitude() + ", "
            + c.getLongitude());
        gotLocation((float)c.getLatitude(), (float)c.getLongitude());
      }        
    });
  }
}
