/*
 * Copyright 2014 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.core.ext.linker;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompilerOptionsImpl;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.OptionOptimize;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.util.tools.Utility;

import junit.framework.TestCase;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/**
 * Basic tests for Source maps and (new) soyc reports.
 */
public class SymbolMapTest extends TestCase {

  private static File[] filterByName(File dir, final String namePattern) {
    return dir.listFiles(new FileFilter() {
      @Override
      public boolean accept(File pathname) {
        return pathname.getName().matches(namePattern);
      }
    });
  }

  /**
   * This class represents each row in a generated SymbolMap file.  Because not all fields are
   * serialized, such as CastableTypeMap, some methods are not implemented.
   *
   */
  static final class SimpleSymbolData implements SymbolData {

    static Map<String, SimpleSymbolData> readSymbolMap(File filePath) throws IOException {
      Map<String, SimpleSymbolData> sdata = Maps.newLinkedHashMap();

      BufferedReader reader = new BufferedReader(new FileReader(filePath));
      String line;
      while ((line = reader.readLine()) != null) {
        if (line.startsWith("#")) {
          // reading a comment
          continue;
        }

        SimpleSymbolData symbolData = new SimpleSymbolData(line);
        String key = symbolData.getJsniIdent();
        assertFalse("Duplicate signature <" + key + "> in symbol maps", sdata.containsKey(key));
        sdata.put(key,symbolData);
      }

      return sdata;
    }

    private static final String NOT_IMPLEMENTED_MESSAGE =
        "Data not available in current serialized SymbolMap";

    private String jsName;
    private String jsniIdent;
    private String className;
    private String memberName;
    private String sourceUri;
    private int sourceLine;
    private int fragmentNumber;

    public SimpleSymbolData(String line) {
      this.parseFromLine(line);
    }

    @Override
    public String getClassName() {
      return this.className;
    }

    @Override
    public int getFragmentNumber() {
      return this.fragmentNumber;
    }

    @Override
    public String getJsniIdent() {
      return this.jsniIdent;
    }

    @Override
    public String getMemberName() {
      return this.memberName;
    }

    @Override
    public String getRuntimeTypeId() {
      throw new UnsupportedOperationException(NOT_IMPLEMENTED_MESSAGE);
    }

    @Override
    public int getSourceLine() {
      return this.sourceLine;
    }

    @Override
    public String getSourceUri() {
      return this.sourceUri;
    }

    @Override
    public String getSymbolName() {
      return this.jsName;
    }

    @Override
    public boolean isClass() {
      return this.memberName == null || this.memberName.isEmpty();
    }

    @Override
    public boolean isField() {
      return !this.isClass() && jsniIdent.indexOf("(") < 0;
    }

    @Override
    public boolean isMethod() {
      return !this.isClass() && jsniIdent.indexOf("(") >= 0;
    }

    @Override
    public String toString() {
      return jsniIdent + " -> " + jsName;
    }

    private void parseFromLine(String line) {
      String[] fields = line.split(",");

      this.jsName = fields[0];
      this.jsniIdent = fields[1].isEmpty() ? fields[2] : fields[1];
      this.className = fields[2];
      this.memberName = fields[3]; // may be empty
      this.sourceUri = fields[4];
      this.sourceLine = Integer.parseInt(fields[5]);
      this.fragmentNumber = Integer.parseInt(fields[6]);
    }
  }

  /**
   * Loads the symbol map from a file.
   */
  private Iterable<Map<String, SimpleSymbolData>> loadSymbolMaps(File root) throws Exception {
    // Testing SourceMaps as SymbolMap replacement
    // make sure the files have been produced
    assertTrue(root.exists());

    File[] symbolMapFiles = filterByName(root, "(.*)\\.symbolMap");

    assertTrue(symbolMapFiles.length >= 1);

    return Iterables.transform(Arrays.asList(symbolMapFiles),
        new Function<File, Map<String, SimpleSymbolData>>() {
          @Override
          public Map<String, SimpleSymbolData> apply(File file) {
            try {
              return SimpleSymbolData.readSymbolMap(file);
            } catch (IOException e) {
              fail("Error reading symbol map " + file.getAbsolutePath());
            }
            return null;
          }
        });
  }

  private static final String JSE_METHOD =
      "com.google.gwt.core.client.JavaScriptException::getThrown()Ljava/lang/Object;";
  private static final String JSE_FIELD = "com.google.gwt.core.client.JavaScriptException::message";
  private static final String JSE_CLASS = "com.google.gwt.core.client.JavaScriptException";
  private static final String UNINSTANTIABLE_CLASS = "com.google.gwt.lang.Array";

  /**
   * Tests for the presence of some elements.
   */
  private void assertSymbolMapSanity(int optimizeLevel) throws IOException,
      UnableToCompleteException, Exception {
    String benchmark = "hello";
    String module = "com.google.gwt.sample.hello.Hello";

    File work = Utility.makeTemporaryDirectory(null, benchmark + "work");
    try {
      CompilerOptionsImpl options = new CompilerOptionsImpl();
      options.addModuleName(module);
      options.setWarDir(new File(work, "war"));
      options.setExtraDir(new File(work, "extra"));
      options.setOptimizationLevel(optimizeLevel);
      PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
      logger.setMaxDetail(TreeLogger.ERROR);
      new com.google.gwt.dev.Compiler(options).run(logger);
      // Change parentDir for cached/pre-built reports
      String parentDir = options.getExtraDir() + "/" + benchmark;
      for (Map<String, SimpleSymbolData> symbolDataByJsniIdentifier :
          loadSymbolMaps(new File(parentDir + "/symbolMaps/"))) {
        assertTrue(!symbolDataByJsniIdentifier.isEmpty());
        assertNotNull(symbolDataByJsniIdentifier.get(JSE_METHOD));
        assertTrue(symbolDataByJsniIdentifier.get(JSE_METHOD).isMethod());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_METHOD).isField());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_METHOD).isClass());
        assertNotNull(symbolDataByJsniIdentifier.get(JSE_FIELD));
        assertTrue(symbolDataByJsniIdentifier.get(JSE_FIELD).isField());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_FIELD).isMethod());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_FIELD).isClass());
        assertNotNull(symbolDataByJsniIdentifier.get(JSE_CLASS));
        assertTrue(symbolDataByJsniIdentifier.get(JSE_CLASS).isClass());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_CLASS).isField());
        assertFalse(symbolDataByJsniIdentifier.get(JSE_CLASS).isMethod());
        if (optimizeLevel == OptionOptimize.OPTIMIZE_LEVEL_DRAFT) {
          assertNotNull(symbolDataByJsniIdentifier.get(UNINSTANTIABLE_CLASS));
        } else {
          assertNull(symbolDataByJsniIdentifier.get(UNINSTANTIABLE_CLASS));
        }
        assertSymbolUniquenessForMethods(symbolDataByJsniIdentifier);
      }
    } finally {
      Util.recursiveDelete(work, false);
    }
  }

  private void assertSymbolUniquenessForMethods(
      Map<String, SimpleSymbolData> symbolDataByJsniIdentifier) {
    Multimap<String, SymbolData> methodSymbolDataBySymbol = HashMultimap.create();
    for (SymbolData symbolData : symbolDataByJsniIdentifier.values()) {
      if (symbolData.isMethod()) {
        methodSymbolDataBySymbol.put(symbolData.getSymbolName(), symbolData);
      }
    }
    Iterator<String> iterator = methodSymbolDataBySymbol.keySet().iterator();
    while (iterator.hasNext()) {
      String key = iterator.next();
      if (methodSymbolDataBySymbol.get(key).size() <= 1) {
        iterator.remove();
      }
    }
    assertTrue("The following method symbols where not unique " + methodSymbolDataBySymbol,
        methodSymbolDataBySymbol.isEmpty());
  }

  public void testSymbolMapSanityDraft() throws Exception {
    assertSymbolMapSanity(OptionOptimize.OPTIMIZE_LEVEL_DRAFT);
  }

  public void testSymbolMapSanityOptimized() throws Exception {
    assertSymbolMapSanity(OptionOptimize.OPTIMIZE_LEVEL_MAX);
  }
}
