/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the
 * NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF
 * licenses this file to you 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 org.apache.pig.pigunit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.Assert;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.pig.ExecType;
import org.apache.pig.ExecTypeProvider;
import org.apache.pig.PigException;
import org.apache.pig.backend.executionengine.ExecException;
import org.apache.pig.data.DataType;
import org.apache.pig.data.Tuple;
import org.apache.pig.impl.PigContext;
import org.apache.pig.impl.io.FileLocalizer;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.logicalLayer.schema.Schema;
import org.apache.pig.pigunit.pig.PigServer;
import org.apache.pig.tools.parameters.ParseException;

/**
 * Pig Unit
 *
 * <p>Equivalent of xUnit for testing Pig.
 *
 * <p>Call {@link PigTest#getCluster()} then construct a test and call an assert method.
 * Have a look to the test of this class for more example.
 */
public class PigTest {
  /** The text of the Pig script to test with no substitution or change. */
  private final String originalTextPigScript;
  /** The list of arguments of the script. */
  private final String[] args;
  /** The list of file arguments of the script. */
  private final String[] argFiles;
  /** The list of aliases to override in the script. */
  private final Map<String, String> aliasOverrides;

  private static ThreadLocal<PigServer> pig = new ThreadLocal<PigServer>();
  private static ThreadLocal<Cluster> cluster = new ThreadLocal<Cluster>();

  private static final Logger LOG = Logger.getLogger(PigTest.class);
  private static final String EXEC_CLUSTER = "pigunit.exectype";

  /**
   * Initializes the Pig test.
   *
   * @param args The list of arguments of the script.
   * @param argFiles The list of file arguments of the script.
   * @param pigTextScript The text of the Pig script to test with no substitution or change.
   */
  @SuppressWarnings("serial")
  PigTest(String[] args, String[] argFiles, String pigTextScript) {
    this.originalTextPigScript = pigTextScript;
    this.args = args;
    this.argFiles = argFiles;
    this.aliasOverrides = new HashMap<String, String>() {{
      put("STORE", "");
      put("DUMP", "");
    }};
  }

  public PigTest(String scriptPath) throws IOException {
    this(null, null, readFile(scriptPath));
  }

  public PigTest(String[] script) {
    this(null, null, StringUtils.join(script, "\n"));
  }

  public PigTest(String scriptPath, String[] args) throws IOException {
    this(args, null, readFile(scriptPath));
  }

  public PigTest(String[] script, String[] args) {
    this(args, null, StringUtils.join(script, "\n"));
  }

  public PigTest(String[] script, String[] args, String[] argsFile) {
    this(args, argsFile, StringUtils.join(script, "\n"));
  }

  public PigTest(String scriptPath, String[] args, String[] argFiles) throws IOException {
    this(args, argFiles, readFile(scriptPath));
  }

  public PigTest(String scriptPath, String[] args, PigServer pig, Cluster cluster)
      throws IOException {
    this(args, null, readFile(scriptPath));
    PigTest.pig.set(pig);
    PigTest.cluster.set(cluster);
  }

  /**
   * Connects and starts if needed the PigServer.
   *
   * @return Reference to the Cluster in ThreadLocal.
   * @throws ExecException If the PigServer can't be started.
   */
  public static Cluster getCluster() throws ExecException {
    try {
      if (cluster.get() == null) {
        ExecType execType = ExecType.LOCAL;
        if (System.getProperties().containsKey(EXEC_CLUSTER)) {
          if (System.getProperties().getProperty(EXEC_CLUSTER).equalsIgnoreCase("mr")) {
            LOG.info("Using mr cluster mode");
            execType = ExecType.MAPREDUCE;
          } else if (System.getProperties().getProperty(EXEC_CLUSTER).equalsIgnoreCase("tez")) {
            LOG.info("Using tez cluster mode");
            execType = ExecTypeProvider.fromString("tez");
          } else if (System.getProperties().getProperty(EXEC_CLUSTER).equalsIgnoreCase("tez_local")) {
            LOG.info("Using tez local mode");
            execType = ExecTypeProvider.fromString("tez_local");
          } else if (System.getProperties().getProperty(EXEC_CLUSTER).equalsIgnoreCase("spark")) {
              LOG.info("Using spark cluster mode");
              execType = ExecTypeProvider.fromString("spark");
          } else if (System.getProperties().getProperty(EXEC_CLUSTER).equalsIgnoreCase("spark_local")) {
              LOG.info("Using spark local cluster mode");
              execType = ExecTypeProvider.fromString("spark_local");
          } else {
            LOG.info("Using default local mode");
          }
        } else {
          LOG.info("Using default local mode");
        }
        pig.set(new PigServer(execType));
        cluster.set(new Cluster(pig.get().getPigContext()));
      }
    } catch (PigException e) {
      throw new ExecException(e);
    }

    return cluster.get();
  }

  /**
   * Return the PigServer.
   *
   * @return Reference to the PigServer in ThreadLocal.
   */
  public static PigServer getPigServer() {
    return pig.get();
  }

  /**
   * Registers a pig scripts with its variables substituted.
   *
   * @throws IOException If a temp file containing the pig script could not be created.
   * @throws ParseException The pig script could not have all its variables substituted.
   */
  protected void registerScript() throws IOException, ParseException {
    getCluster();

    BufferedReader reader = new BufferedReader(new StringReader(this.originalTextPigScript));
    PigContext context = getPigServer().getPigContext();

    String substitutedPig = context.doParamSubstitution(reader,
                                                        args == null ? null : Arrays.asList(args),
                                                        argFiles == null ? null : Arrays.asList(argFiles));
    LOG.info(substitutedPig);

    File f = File.createTempFile("tmp", "pigunit");
    PrintWriter pw = new PrintWriter(f);
    pw.println(substitutedPig);
    pw.close();

    String pigSubstitutedFile = f.getCanonicalPath();
    getPigServer().registerScript(pigSubstitutedFile, aliasOverrides);
  }

  /**
   * Executes the Pig script with its current overrides.
   *
   * @throws IOException If a temp file containing the pig script could not be created.
   * @throws ParseException The pig script could not have all its variables substituted.
   */
  public void runScript() throws IOException, ParseException {
    registerScript();
  }

  /**
   * Gets an iterator on the content of one alias of the script.
   *
   * <p>For now use a giant String in order to display all the differences in one time. It might not
   * work with giant expected output.
   * @throws ParseException If the Pig script could not be parsed.
   * @throws IOException If the Pig script could not be executed correctly.
   */
  public Iterator<Tuple> getAlias(String alias) throws IOException, ParseException {
    registerScript();
    return getPigServer().openIterator(alias);
  }
  
  /**
   * Gets an iterator on the content of one alias of a cached script. The script itself
   * must be already be registered with registerScript().
   */
  private Iterator<Tuple> getAliasFromCache(String alias) throws IOException, ParseException {
    return getPigServer().openIterator(alias);
  }

  /**
   * Gets an iterator on the content of the latest STORE alias of the script.
   *
   * @throws ParseException If the Pig script could not be parsed.
   * @throws IOException If the Pig script could not be executed correctly.
   */
  public Iterator<Tuple> getAlias() throws IOException, ParseException {
    registerScript();
    String alias = aliasOverrides.get("LAST_STORE_ALIAS");

    return getAliasFromCache(alias);
  }

  /**
   * Replaces the query of an aliases by another query.
   *
   * <p>For example:
   *
   * <pre>
   * B = FILTER A BY count > 5;
   * overridden with:
   * &lt;B, B = FILTER A BY name == 'Pig';&gt;
   * becomes
   * B = FILTER A BY name == 'Pig';
   * </pre>
   *
   * @param alias The alias to override.
   * @param query The new value of the alias.
   */
  public void override(String alias, String query) {
    aliasOverrides.put(alias, query);
  }

  public void unoverride(String alias) {
    aliasOverrides.remove(alias);
  }

  /**
   * Returns a Map that has alias to it's schema.
   *
   * @return A map that has alias name as a key and the alias's schema as a value
   * @throws FrontendException If there was an error dumping the schema
   */
  public Map<String, String> getAliasToSchemaMap() throws FrontendException, IOException, ParseException {
    HashMap<String, String> aliasSchemas = new HashMap<String, String>();
    registerScript();
    PigServer server = getPigServer();
    Set<String> aliasKeySet = server.getAliasKeySet();
    for (String alias: aliasKeySet) {
      try {
        StringBuilder tsb = new StringBuilder();
        Schema.stringifySchema(tsb, server.dumpSchema(alias), DataType.TUPLE, Integer.MIN_VALUE);
        aliasSchemas.put(alias, tsb.toString());
      } catch (FrontendException e) {
        /**
         * If PigServer fails to describe a schema for an alias a FrontendException is thrown.
         * PigServer.getAliasKeySet() returns aliases that cannot have their schema described.
         * We want to skip over these particular aliases.
         */
        if (e.getErrorCode() == 1001) {
          //Let's print a warning
          System.out.println(e.getMessage());
        } else {
          throw e;
        }
      }
    }
    return aliasSchemas;
  }

  /**
   * Creates a temp file and populates it with the specified mock data.
   *
   * @param alias alias that the temp file is for
   * @param mockData data that is being mocked for the alias
   * @return path to the temp file
   */
  private String makeMockTempFile(String alias, String[] mockData) throws IOException {
    //The FileLocalizer uses a random variable, but that can have collisions. By using the current time, thread,
    //and alias we should be able to guaratee a unique file
    String uniqueSuffix = alias + "." + System.currentTimeMillis() + "." + Thread.currentThread().getId();
    //PigServer/Cluster is not initialized yet. Let's initialize it.
    if (getPigServer() == null) {
        getCluster();
    }
    String path = FileLocalizer.getTemporaryPath(getPigServer().getPigContext(), uniqueSuffix).toString();
    getCluster().copyFromLocalFile(mockData, path, true);
    return path;
  }

  private String getActualResults(String alias, boolean ignoreOrder) throws IOException, ParseException {
    //Tuples are sortable, but we should sort it as Strings for convenience when comparing to expected data
    Iterator<Tuple> iterator = getAliasFromCache(alias);
    List<String> actualResults = new ArrayList<String>();
    while (iterator.hasNext()) {
      actualResults.add(iterator.next().toString());
    }
    
    if (ignoreOrder) {
      Collections.sort(actualResults);
    }
    return StringUtils.join(actualResults, "\n");
  }

  /**
   * Allows you to mock a specific alias.
   *
   * This method will create a temporary file on the system that contains the mock data.  It will then change the pig
   * script to actually replace the alias when being assigned a value with a load file command which loads the temporary
   * file.
   *
   * @param alias The alias to be mocked
   * @param mockData The data you wished to be contained in the alias where each element in the array is a tab-delimited
   * @param aliasSchema The schema of the alias provided. Your mockData should fit this schema
   */
  public void mockAlias(String alias, String[] mockData, String aliasSchema) throws IOException {
    mockAlias(alias, mockData, aliasSchema, "\\t");
  }

  /**
   * Allows you to mock a specific alias.
   *
   * This method will create a temporary file on the system that contains the mock data.  It will then change the pig
   * script to actually replace the alias when being assigned a value with a load file command which loads the temporary
   * file.
   *
   * @param alias The alias to be mocked
   * @param mockData String array where each element is an entry in the alias and the line has its elements delimited
   *                 by the value provided by delimiter.
   * @param aliasSchema This is the schema of the alias being mocked
   * @param delimiter The delimiter used to separate data in mockData
   */
  public void mockAlias(String alias, String[] mockData, String aliasSchema, String delimiter) throws IOException {
    String mockFile = makeMockTempFile(alias, mockData);
    override(alias, String.format("%s = LOAD '%s' USING PigStorage('%s') AS %s;", alias, mockFile, delimiter, aliasSchema));
  }
  
  /**
   * Compares the expected results to the results of the last alias generated in the script. Order does not matter
   * and as long as the result is located in any index of expected and any line of the output then this will pass.
   * 
   * @param expected The expected results
   */
  public void assertOutputAnyOrder(String[] expected) throws IOException, ParseException {
    assertOutput(expected, true);
  }
  
  public void assertOutput(String[] expected) throws IOException, ParseException {
    assertOutput(expected, false);
  }

  private void assertOutput(String[] expected, boolean ignoreOrder) throws IOException, ParseException {
    registerScript();
    String alias = aliasOverrides.get("LAST_STORE_ALIAS");

    if (ignoreOrder) {
      Arrays.sort(expected);
    }
    assertEquals(StringUtils.join(expected, "\n"), getActualResults(alias, ignoreOrder));
  }
  
  /**
   * Compares the expected results to the results of the provided alias's output. Order does not matter
   * and as long as the result is located in any index of expected and any line of the output then this will pass.
   * 
   * @param alias The alias whose results we want to check
   * @param expected The expected results
   */
  public void assertOutputAnyOrder(String alias, String[] expected) throws IOException, ParseException {
    assertOutput(alias, expected, true);
  }
  
  public void assertOutput(String alias, String[] expected) throws IOException, ParseException {
    assertOutput(alias, expected, false);
  }

  private void assertOutput(String alias, String[] expected, boolean ignoreOrder) throws IOException, ParseException {
    registerScript();

    if (ignoreOrder) {
      Arrays.sort(expected);
    }
    assertEquals(StringUtils.join(expected, "\n"), getActualResults(alias, ignoreOrder));
  }

  public void assertOutput(File expected) throws IOException, ParseException {
    assertOutput(readFile(expected).split("(\\r\\n|\\n)"), false);
  }
  
  public void assertOutput(String alias, File expected) throws IOException, ParseException {
    assertOutput(alias, readFile(expected).split("(\\r\\n|\\n)"), false);
  }
  
  public void assertOutput(String aliasInput, String[] input, String alias, String[] expected)
      throws IOException, ParseException {
    assertOutput(aliasInput, input, alias, expected, "\\t");
  }
  
  public void assertOutput(String aliasInput, String[] input, String alias, String[] expected, String delimiter)
      throws IOException, ParseException {
    registerScript();

    StringBuilder sb = new StringBuilder();
    Schema.stringifySchema(sb, getPigServer().dumpSchema(aliasInput), DataType.TUPLE) ;

    mockAlias(aliasInput, input, sb.toString(), delimiter);

    assertOutput(alias, expected, false);
  }

  protected void assertEquals(String expected, String current) {
    Assert.assertEquals(expected, current);
  }
  
  private static String readFile(String path) throws IOException {
    return readFile(new File(path));
  }

  private static String readFile(File file) throws IOException {
    FileInputStream stream = new FileInputStream(file);
    try {
      FileChannel fc = stream.getChannel();
      MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
      return Charset.defaultCharset().decode(bb).toString();
    }
    finally {
      stream.close();
    }
  }
}
