/*
 * Copyright 2006 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.dev.shell;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
import com.google.gwt.dev.About;
import com.google.gwt.dev.GwtVersion;
import com.google.gwt.dev.shell.ie.CheckForUpdatesIE6;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.prefs.Preferences;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Orchestrates a best-effort attempt to find out if a new version of GWT is
 * available.
 */
public class CheckForUpdates {

  /**
   * Returns the result of an update check.
   */
  public interface UpdateResult {
    /**
     * @return the new version of GWT available.
     */
    GwtVersion getNewVersion();

    /**
     * @return the URL for details about the new version.
     */
    URL getURL();
  }

  public static final long ONE_DAY = 24 * 60 * 60 * 1000;
  public static final long ONE_MINUTE = 60 * 1000;

  // System properties used by CheckForUpdates
  protected static final String PROPERTY_DEBUG_HTTP_GET = "gwt.debugLowLevelHttpGet";
  protected static final String PROPERTY_FORCE_NONNATIVE = "gwt.forceVersionCheckNonNative";
  protected static final String PROPERTY_PREFS_NAME = "gwt.prefsPathName";
  protected static final String PROPERTY_QUERY_URL = "gwt.forceVersionCheckURL";

  // Log levels -- in general we want the logging of the update process
  // to not be visible to normal users.
  private static final TreeLogger.Type CHECK_ERROR = TreeLogger.DEBUG;
  private static final TreeLogger.Type CHECK_INFO = TreeLogger.SPAM;
  private static final TreeLogger.Type CHECK_SPAM = TreeLogger.SPAM;
  private static final TreeLogger.Type CHECK_WARN = TreeLogger.SPAM;

  // Preferences keys
  private static final String FIRST_LAUNCH = "firstLaunch";
  private static final String HIGHEST_RUN_VERSION = "highestRunVersion";
  private static final String LAST_PING = "lastPing";
  private static final String NEXT_PING = "nextPing";

  // Uncomment one of constants below to try different variations of failure to
  // make sure we never interfere with the app running.

  // Check against a fake server to see failure to contact server.
  // protected static final String QUERY_URL =
  // "http://nonexistenthost:1111/gwt/currentversion.xml";

  // Check 404 on a real location that doesn't have the file.
  // protected static final String QUERY_URL =
  // "http://www.google.com/gwt/currentversion.xml";

  // A test URL for seeing it actually work in a sandbox.
  // protected static final String QUERY_URL =
  // "http://localhost/gwt/currentversion.xml";

  // The real URL that should be used.
  private static final String QUERY_URL = "http://tools.google.com/webtoolkit/currentversion.xml";

  public static FutureTask<UpdateResult> checkForUpdatesInBackgroundThread(
      final TreeLogger logger, final long minCheckMillis) {
    final String entryPoint = computeEntryPoint();
    FutureTask<UpdateResult> task = new FutureTask<UpdateResult>(
        new Callable<UpdateResult>() {
          public UpdateResult call() throws Exception {
            final CheckForUpdates updateChecker = createUpdateChecker(logger,
                entryPoint);
            return updateChecker == null ? null
                : updateChecker.check(minCheckMillis);
          }
        });
    Thread checkerThread = new Thread(task, "GWT Update Checker");
    checkerThread.setDaemon(true);
    checkerThread.start();
    return task;
  }

  /**
   * Find the first method named "main" on the call stack and use its class as
   * the entry point.
   */
  public static String computeEntryPoint() {
    Throwable t = new Throwable();
    for (StackTraceElement stackTrace : t.getStackTrace()) {
      if (stackTrace.getMethodName().equals("main")) {
        // Strip package name from main's class
        String className = stackTrace.getClassName();
        int i = className.lastIndexOf('.');
        if (i >= 0) {
          return className.substring(i + 1);
        }
        return className;
      }
    }
    return null;
  }

  public static CheckForUpdates createUpdateChecker(TreeLogger logger) {
    return createUpdateChecker(logger, computeEntryPoint());
  }

  public static CheckForUpdates createUpdateChecker(TreeLogger logger,
      String entryPoint) {
    // Windows has a custom implementation to handle proxies.
    if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win")) {
      return new CheckForUpdatesIE6(logger, entryPoint);
    } else {
      return new CheckForUpdates(logger, entryPoint);
    }
  }

  public static void logUpdateAvailable(TreeLogger logger,
      FutureTask<UpdateResult> updater) {
    if (updater != null && updater.isDone()) {
      UpdateResult result = null;
      try {
        result = updater.get(0, TimeUnit.MILLISECONDS);
      } catch (InterruptedException e) {
        // Silently ignore exception
      } catch (ExecutionException e) {
        // Silently ignore exception
      } catch (TimeoutException e) {
        // Silently ignore exception
      }
      logUpdateAvailable(logger, result);
    }
  }

  public static void logUpdateAvailable(TreeLogger logger,
      UpdateResult result) {
    if (result != null) {
      final URL url = result.getURL();
      logger.log(TreeLogger.WARN, "A new version of GWT ("
          + result.getNewVersion() + ") is available", null, new HelpInfo() {
            @Override
            public String getAnchorText() {
              return "Release Notes";
            }
    
            @Override
            public URL getURL() {
              return url;
            }
          });
    }
  }

  private static String getTextOfLastElementHavingTag(Document doc,
      String tagName) {
    NodeList nodeList = doc.getElementsByTagName(tagName);
    int n = nodeList.getLength();
    if (n > 0) {
      Element elem = (Element) nodeList.item(n - 1);
      // Assume the first child is the value.
      //
      Node firstChild = elem.getFirstChild();
      if (firstChild != null) {
        String text = firstChild.getNodeValue();
        return text;
      }
    }

    return null;
  }

  private String entryPoint;

  private TreeLogger logger;

  private GwtVersion myVersion;

  /**
   * Create an update checker which will poll a server URL and log a message
   * about an update if available.
   * 
   * @param logger TreeLogger to use
   * @param entryPoint the name of the main entry point used for this execution
   */
  public CheckForUpdates(TreeLogger logger, String entryPoint) {
    this.logger = logger;
    this.entryPoint = entryPoint;
    myVersion = About.getGwtVersionObject();
  }

  /**
   * Check for updates and log to the logger if they are available.
   * 
   * @return an UpdateResult or null if there is no new update
   */
  public UpdateResult check() {
    return check(0);
  }

  /**
   * Check for updates and log to the logger if they are available.
   * 
   * @return an UpdateResult or null if there is no new update
   */
  public UpdateResult check(long minCheckMillis) {
    TreeLogger branch = logger.branch(CHECK_INFO, "Checking for updates");
    try {
      String prefsName = System.getProperty(PROPERTY_PREFS_NAME);
      Preferences prefs;
      if (prefsName != null) {
        prefs = Preferences.userRoot().node(prefsName);
      } else {
        prefs = Preferences.userNodeForPackage(CheckForUpdates.class);
      }

      String queryURL = QUERY_URL;
      String forceCheckURL = System.getProperty(PROPERTY_QUERY_URL);

      if (forceCheckURL != null) {
        branch.log(CHECK_INFO, "Explicit version check URL: " + forceCheckURL);
        queryURL = forceCheckURL;
      }

      // Get our unique user id (based on absolute timestamp).
      //
      long currentTimeMillis = System.currentTimeMillis();
      String firstLaunch = prefs.get(FIRST_LAUNCH, null);
      if (firstLaunch == null) {
        firstLaunch = Long.toHexString(currentTimeMillis);
        prefs.put(FIRST_LAUNCH, firstLaunch);
        branch.log(CHECK_SPAM, "Setting first launch to " + firstLaunch);
      } else {
        branch.log(CHECK_SPAM, "First launch was " + firstLaunch);
      }

      // See if enough time has passed.
      //
      String lastPing = prefs.get(LAST_PING, "0");
      if (lastPing != null) {
        try {
          long lastPingTime = Long.parseLong(lastPing);
          if (currentTimeMillis < lastPingTime + minCheckMillis) {
            // it's not time yet
            branch.log(CHECK_INFO, "Last ping was " + new Date(lastPingTime)
                + ", min wait is " + minCheckMillis + "ms");
            return null;
          }
        } catch (NumberFormatException e) {
          branch.log(CHECK_WARN, "Error parsing last ping time", e);
        }
      }

      // See if it's time for our next ping yet.
      //
      String nextPing = prefs.get(NEXT_PING, "0");
      if (nextPing != null) {
        try {
          long nextPingTime = Long.parseLong(nextPing);
          if (currentTimeMillis < nextPingTime) {
            // it's not time yet
            branch.log(CHECK_INFO, "Next ping is not until "
                + new Date(nextPingTime));
            return null;
          }
        } catch (NumberFormatException e) {
          branch.log(CHECK_WARN, "Error parsing next ping time", e);
        }
      }

      // See if new version is available.
      //
      String url = queryURL + "?v=" + myVersion.toString() + "&id="
          + firstLaunch + "&r=" + About.getGwtSvnRev();
      if (entryPoint != null) {
        url += "&e=" + entryPoint;
      }

      branch.log(CHECK_INFO, "Checking for new version at " + url);

      // Do the HTTP GET.
      //
      byte[] response;
      String fullUserAgent = makeUserAgent();
      if (System.getProperty(PROPERTY_FORCE_NONNATIVE) == null) {
        // Use subclass.
        //
        response = doHttpGet(branch, fullUserAgent, url);
      } else {
        // Use the pure Java version, but it probably doesn't work with proxies.
        //
        response = httpGetNonNative(branch, fullUserAgent, url);
      }

      if (response == null || response.length == 0) {
        // Problem. Quietly fail.
        //
        branch.log(CHECK_ERROR,
            "Failed to obtain current version info via HTTP");
        return null;
      }

      // Parse and process the response.
      // Bad responses will be silently ignored.
      //
      return parseResponse(branch, prefs, response);

    } catch (Throwable e) {
      // Always silently ignore any errors.
      //
      branch.log(CHECK_INFO, "Exception while processing version info", e);
    }
    return null;
  }

  /**
   * Default implementation just uses the platform-independent method. A
   * subclass should override this method for platform-dependent proxy handling,
   * for example.
   * 
   * @param branch TreeLogger to use
   * @param userAgent user agent string to send in request
   * @param url URL to fetch
   * @return byte array of response, or null if an error
   */
  protected byte[] doHttpGet(TreeLogger branch, String userAgent, String url) {
    return httpGetNonNative(branch, userAgent, url);
  }

  /**
   * This default implementation uses regular Java HTTP, which doesn't deal with
   * proxies automagically. See the IE6 subclasses for an implementation that
   * does deal with proxies.
   * 
   * @param branch TreeLogger to use
   * @param userAgent user agent string to send in request
   * @param url URL to fetch
   * @return byte array of response, or null if an error
   */
  protected byte[] httpGetNonNative(TreeLogger branch, String userAgent,
      String url) {
    Throwable caught;
    InputStream is = null;
    try {
      URL urlToGet = new URL(url);
      URLConnection conn = urlToGet.openConnection();
      conn.setRequestProperty("User-Agent", userAgent);
      is = conn.getInputStream();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] buffer = new byte[4096];
      int bytesRead;
      while ((bytesRead = is.read(buffer)) != -1) {
        baos.write(buffer, 0, bytesRead);
      }
      byte[] response = baos.toByteArray();
      return response;
    } catch (MalformedURLException e) {
      caught = e;
    } catch (IOException e) {
      caught = e;
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
        }
      }
    }

    if (System.getProperty(PROPERTY_DEBUG_HTTP_GET) != null) {
      branch.log(CHECK_ERROR, "Exception in HTTP request", caught);
    }

    return null;
  }

  private void appendUserAgentProperty(StringBuffer sb, String propName) {
    String propValue = System.getProperty(propName);
    if (propValue != null) {
      if (sb.length() > 0) {
        sb.append("; ");
      }
      sb.append(propName);
      sb.append("=");
      sb.append(propValue);
    }
  }

  /**
   * Creates a user-agent string by combining standard Java properties.
   */
  private String makeUserAgent() {
    String ua = "GWT Freshness Checker";

    StringBuffer extra = new StringBuffer();
    appendUserAgentProperty(extra, "java.vendor");
    appendUserAgentProperty(extra, "java.version");
    appendUserAgentProperty(extra, "os.arch");
    appendUserAgentProperty(extra, "os.name");
    appendUserAgentProperty(extra, "os.version");

    if (extra.length() > 0) {
      ua += " (" + extra.toString() + ")";
    }

    return ua;
  }

  private UpdateResult parseResponse(TreeLogger branch, Preferences prefs,
      byte[] response) throws IOException, ParserConfigurationException,
      SAXException {

    branch.log(CHECK_SPAM, "Parsing response (length " + response.length + ")");

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    ByteArrayInputStream bais = new ByteArrayInputStream(response);

    // Parse the XML.
    //
    builder.setErrorHandler(new ErrorHandler() {

      public void error(SAXParseException exception) throws SAXException {
        // fail quietly
      }

      public void fatalError(SAXParseException exception) throws SAXException {
        // fail quietly
      }

      public void warning(SAXParseException exception) throws SAXException {
        // fail quietly
      }
    });
    Document doc = builder.parse(bais);

    // The latest version number.
    //
    String versionString = getTextOfLastElementHavingTag(doc, "latest-version");
    if (versionString == null) {
      // Not valid; quietly fail.
      //
      branch.log(CHECK_ERROR, "Failed to find <latest-version>");
      return null;
    }
    GwtVersion currentReleasedVersion;
    try {
      currentReleasedVersion = new GwtVersion(versionString.trim());
    } catch (NumberFormatException e) {
      branch.log(CHECK_ERROR, "Bad version: " + versionString, e);
      return null;
    }

    // Ping delay for server-controlled throttling.
    //
    String pingDelaySecsStr = getTextOfLastElementHavingTag(doc,
        "min-wait-seconds");
    int pingDelaySecs = 0;
    if (pingDelaySecsStr == null) {
      // Not valid; quietly fail.
      //
      branch.log(CHECK_ERROR, "Missing <min-wait-seconds>");
      return null;
    }
    try {
      pingDelaySecs = Integer.parseInt(pingDelaySecsStr.trim());
    } catch (NumberFormatException e) {
      // Not a valid number; quietly fail.
      //
      branch.log(CHECK_ERROR, "Bad min-wait-seconds number: "
          + pingDelaySecsStr);
      return null;
    }

    String url = getTextOfLastElementHavingTag(doc, "notification-url");

    if (url == null) {
      // no URL, so write the HTML locally and provide a URL from that

      // Read the HTML.
      //
      String html = getTextOfLastElementHavingTag(doc, "notification");

      if (html == null) {
        // Not valid; quietly fail.
        //
        branch.log(CHECK_ERROR, "Missing <notification>");
        return null;
      }
      PrintWriter writer = null;
      try {
        String tempDir = System.getProperty("java.io.tmpdir");
        File updateHtml = new File(tempDir, "gwt-update-"
            + currentReleasedVersion + ".html");
        writer = new PrintWriter(new FileOutputStream(updateHtml));
        writer.print(html);
        url = "file://" + updateHtml.getAbsolutePath();
      } finally {
        if (writer != null) {
          writer.close();
        }
      }
    }

    // Okay -- this is a valid response.
    //
    return processResponse(branch, prefs, currentReleasedVersion,
        pingDelaySecs, url);
  }

  private UpdateResult processResponse(TreeLogger branch, Preferences prefs,
      final GwtVersion serverVersion, int pingDelaySecs, final String notifyUrl) {

    // Record a ping; don't ping again until the delay is up.
    //
    long currentTimeMillis = System.currentTimeMillis();
    long nextPingTime = currentTimeMillis + pingDelaySecs * 1000;
    prefs.put(NEXT_PING, String.valueOf(nextPingTime));
    prefs.put(LAST_PING, String.valueOf(currentTimeMillis));

    branch.log(CHECK_INFO, "Ping delay is " + pingDelaySecs + "; next ping at "
        + new Date(nextPingTime));

    if (myVersion.isNoNagVersion()) {
      // If the version number indicates no nagging about updates, exit here
      // once we have recorded the next ping time. No-nag versions (ie,
      // trunk builds) should also not update the highest version that has been
      // run.
      return null;
    }

    // Update the highest version of GWT that has been run if we are later.
    GwtVersion highestRunVersion = new GwtVersion(prefs.get(
        HIGHEST_RUN_VERSION, null));
    if (myVersion.compareTo(highestRunVersion) > 0) {
      highestRunVersion = myVersion;
      prefs.put(HIGHEST_RUN_VERSION, highestRunVersion.toString());
    }

    // Are we up to date already?
    //
    if (highestRunVersion.compareTo(serverVersion) >= 0) {
      // Yes, we are.
      //
      branch.log(CHECK_INFO, "Server version (" + serverVersion
          + ") is not newer than " + highestRunVersion);
      return null;
    }

    // Commence nagging.
    //
    URL url = null;
    try {
      url = new URL(notifyUrl);
    } catch (MalformedURLException e) {
      logger.log(CHECK_ERROR, "Malformed notify URL: " + notifyUrl, e);
    }
    final URL finalUrl = url;
    return new UpdateResult() {
      public GwtVersion getNewVersion() {
        return serverVersion;
      }

      public URL getURL() {
        return finalUrl;
      }
    };
  }
}
