/*
 * Copyright 2011 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.useragent.rebind;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.StringSourceWriter;

import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;

/**
 * Generator which writes out the JavaScript for determining the value of the
 * <code>user.agent</code> selection property.
 */
public class UserAgentPropertyGenerator implements PropertyProviderGenerator {

  /**
   * The list of {@code user.agent} values listed here should be kept in sync with
   * {@code UserAgent.gwt.xml}.
   * <p>Note that the order of enums matter as the script selection is based on running
   * these predicates in order and matching the first one that returns {@code true}.
   * <p> Also note that, {@code docMode < 11} in predicates for older IEs exists to
   * ensures we never choose them for IE11 (we know that they will not work for IE11).
   */
  private enum UserAgent {
    safari("return (ua.indexOf('webkit') != -1);"),
    ie10("return (ua.indexOf('msie') != -1 && (docMode >= 10 && docMode < 11));"),
    ie9("return (ua.indexOf('msie') != -1 && (docMode >= 9 && docMode < 11));"),
    ie8("return (ua.indexOf('msie') != -1 && (docMode >= 8 && docMode < 11));"),
    gecko1_8("return (ua.indexOf('gecko') != -1 || docMode >= 11);");

    private final String predicateBlock;

    private UserAgent(String predicateBlock) {
      this.predicateBlock = predicateBlock;
    }

    private static Set<String> getKnownAgents() {
      HashSet<String> userAgents = new HashSet<String>();
      for (UserAgent userAgent : values()) {
        userAgents.add(userAgent.name());
      }
      return userAgents;
    }
  }

  /**
   * Writes out the JavaScript function body for determining the value of the
   * <code>user.agent</code> selection property. This method is used to create
   * the selection script and by {@link UserAgentGenerator} to assert at runtime
   * that the correct user agent permutation is executing.
   */
  static void writeUserAgentPropertyJavaScript(SourceWriter body,
      SortedSet<String> possibleValues, String fallback) {

    // write preamble
    body.println("var ua = navigator.userAgent.toLowerCase();");
    body.println("var docMode = $doc.documentMode;");

    for (UserAgent userAgent : UserAgent.values()) {
      // write only selected user agents
      if (possibleValues.contains(userAgent.name())) {
        body.println("if ((function() { ");
        body.indentln(userAgent.predicateBlock);
        body.println("})()) return '%s';", userAgent.name());
      }
    }

    // default return
    if (fallback == null) {
      fallback = "unknown";
    }
    body.println("return '" + fallback + "';");
  }

  @Override
  public String generate(TreeLogger logger, SortedSet<String> possibleValues, String fallback,
      SortedSet<ConfigurationProperty> configProperties) {
    assertUserAgents(logger, possibleValues);

    StringSourceWriter body = new StringSourceWriter();
    body.println("{");
    body.indent();
    writeUserAgentPropertyJavaScript(body, possibleValues, fallback);
    body.outdent();
    body.println("}");

    return body.toString();
  }

  private static void assertUserAgents(TreeLogger logger, SortedSet<String> possibleValues) {
    HashSet<String> unknownValues = new HashSet<String>(possibleValues);
    unknownValues.removeAll(UserAgent.getKnownAgents());
    if (!unknownValues.isEmpty()) {
      logger.log(TreeLogger.WARN, "Unrecognized " + UserAgentGenerator.PROPERTY_USER_AGENT
          + " values " + unknownValues + ", possibly due to UserAgent.gwt.xml and "
          + UserAgentPropertyGenerator.class.getName() + " being out of sync.");
    }
  }
}
