/*
 * 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.pirk.querier.wideskies.encrypt;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.pirk.encryption.Paillier;
import org.apache.pirk.querier.wideskies.Querier;
import org.apache.pirk.query.wideskies.Query;
import org.apache.pirk.query.wideskies.QueryInfo;
import org.apache.pirk.query.wideskies.QueryUtils;
import org.apache.pirk.schema.data.DataSchema;
import org.apache.pirk.schema.data.DataSchemaRegistry;
import org.apache.pirk.schema.query.QuerySchema;
import org.apache.pirk.schema.query.QuerySchemaRegistry;
import org.apache.pirk.utils.KeyedHash;
import org.apache.pirk.utils.PIRException;
import org.apache.pirk.utils.SystemConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class to perform PIR encryption
 *
 */
public class EncryptQuery
{
  private static final Logger logger = LoggerFactory.getLogger(EncryptQuery.class);

  // Contains basic query information.
  private final QueryInfo queryInfo;

  // Selectors for this query.
  private final List<String> selectors;

  // Paillier encryption functionality.
  private final Paillier paillier;

  /**
   * Constructs a query encryptor using the given query information, selectors, and Paillier cryptosystem.
   * 
   * @param queryInfo
   *          Fundamental information about the query.
   * @param selectors
   *          the list of selectors for this query.
   * @param paillier
   *          the Paillier cryptosystem to use.
   */
  public EncryptQuery(QueryInfo queryInfo, List<String> selectors, Paillier paillier)
  {
    this.queryInfo = queryInfo;
    this.selectors = selectors;
    this.paillier = paillier;
  }

  /**
   * Encrypts the query described by the query information using Paillier encryption.
   * <p>
   * The encryption builds a <code>Querier</code> object, calculating and setting the query vectors.
   * <p>
   * Uses the system configured number of threads to conduct the encryption, or a single thread if the configuration has not been set.
   * 
   * @throws InterruptedException
   *           If the task was interrupted during encryption.
   * @throws PIRException
   *           If a problem occurs performing the encryption.
   * @return The querier containing the query, and all information required to perform decryption.
   */
  public Querier encrypt() throws InterruptedException, PIRException
  {
    int numThreads = SystemConfiguration.getIntProperty("numThreads", 1);
    return encrypt(numThreads);
  }

  /**
   * Encrypts the query described by the query information using Paillier encryption using the given number of threads.
   * <p>
   * The encryption builds a <code>Querier</code> object, calculating and setting the query vectors.
   * <p>
   * If we have hash collisions over our selector set, we will append integers to the key starting with 0 until we no longer have collisions.
   * <p>
   * For encrypted query vector E = <E_0, ..., E_{(2^hashBitSize)-1}>:
   * <p>
   * E_i = 2^{j*dataPartitionBitSize} if i = H_k(selector_j) 0 otherwise
   * 
   * @param numThreads
   *          the number of threads to use when performing the encryption.
   * @throws InterruptedException
   *           If the task was interrupted during encryption.
   * @throws PIRException
   *           If a problem occurs performing the encryption.
   * @return The querier containing the query, and all information required to perform decryption.
   */
  public Querier encrypt(int numThreads) throws InterruptedException, PIRException
  {
    // Determine the query vector mappings for the selectors; vecPosition -> selectorNum
    Map<Integer,Integer> selectorQueryVecMapping = computeSelectorQueryVecMap();

    // Form the embedSelectorMap
    // Map to check the embedded selectors in the results for false positives;
    // if the selector is a fixed size < 32 bits, it is included as is
    // if the selector is of variable lengths
    Map<Integer,String> embedSelectorMap = computeEmbeddedSelectorMap();

    SortedMap<Integer,BigInteger> queryElements;
    if (numThreads == 1)
    {
      queryElements = serialEncrypt(selectorQueryVecMapping);
      logger.info("Completed serial creation of encrypted query vectors");
    }
    else
    {
      queryElements = parallelEncrypt(selectorQueryVecMapping, Math.max(2, numThreads));
      logger.info("Completed parallel creation of encrypted query vectors");
    }

    Query query = new Query(queryInfo, paillier.getN(), queryElements);

    // Generate the expTable in Query, if we are using it and if
    // useHDFSExpLookupTable is false -- if we are generating it as standalone and not on the cluster
    if (queryInfo.useExpLookupTable() && !queryInfo.useHDFSExpLookupTable())
    {
      logger.info("Starting expTable generation");
      query.generateExpTable();
    }

    // Return the Querier object.
    return new Querier(selectors, paillier, query, embedSelectorMap);
  }

  private Map<Integer,Integer> computeSelectorQueryVecMap()
  {
    String hashKey = queryInfo.getHashKey();
    int keyCounter = 0;
    int numSelectors = selectors.size();
    Map<Integer,Integer> selectorQueryVecMapping = new HashMap<>(numSelectors);

    for (int index = 0; index < numSelectors; index++)
    {
      String selector = selectors.get(index);
      int hash = KeyedHash.hash(hashKey, queryInfo.getHashBitSize(), selector);

      // All keyed hashes of the selectors must be unique
      if (selectorQueryVecMapping.put(hash, index) == null)
      {
        // The hash is unique
        logger.debug("index = " + index + "selector = " + selector + " hash = " + hash);
      }
      else
      {
        // Hash collision
        selectorQueryVecMapping.clear();
        hashKey = queryInfo.getHashKey() + ++keyCounter;
        logger.debug("index = " + index + "selector = " + selector + " hash collision = " + hash + " new key = " + hashKey);
        index = -1;
      }
    }
    return selectorQueryVecMapping;
  }

  private Map<Integer,String> computeEmbeddedSelectorMap() throws PIRException
  {
    QuerySchema qSchema = QuerySchemaRegistry.get(queryInfo.getQueryType());
    String selectorName = qSchema.getSelectorName();
    DataSchema dSchema = DataSchemaRegistry.get(qSchema.getDataSchemaName());
    String type = dSchema.getElementType(selectorName);

    Map<Integer,String> embedSelectorMap = new HashMap<>(selectors.size());

    int sNum = 0;
    for (String selector : selectors)
    {
      String embeddedSelector = QueryUtils.getEmbeddedSelector(selector, type, dSchema.getPartitionerForElement(selectorName));
      embedSelectorMap.put(sNum, embeddedSelector);
      sNum += 1;
    }

    return embedSelectorMap;
  }

  /*
   * Perform the encryption using a single thread, avoiding the overhead of thread management.
   */
  private SortedMap<Integer,BigInteger> serialEncrypt(Map<Integer,Integer> selectorQueryVecMapping) throws PIRException
  {
    int numElements = 1 << queryInfo.getHashBitSize(); // 2^hashBitSize

    EncryptQueryTask task = new EncryptQueryTask(queryInfo.getDataPartitionBitSize(), paillier, selectorQueryVecMapping, 0, numElements - 1);

    return task.call();
  }

  /*
   * Performs the encryption with numThreads.
   */
  private SortedMap<Integer,BigInteger> parallelEncrypt(Map<Integer,Integer> selectorQueryVecMapping, int numThreads) throws InterruptedException, PIRException
  {
    // Encrypt and form the query vector
    ExecutorService es = Executors.newCachedThreadPool();
    List<Future<SortedMap<Integer,BigInteger>>> futures = new ArrayList<>(numThreads);
    int numElements = 1 << queryInfo.getHashBitSize(); // 2^hashBitSize

    // Split the work across the requested number of threads
    int elementsPerThread = numElements / numThreads;
    for (int i = 0; i < numThreads; ++i)
    {
      // Grab the range for this thread
      int start = i * elementsPerThread;
      int stop = start + elementsPerThread - 1;
      if (i == numThreads - 1)
      {
        stop = numElements - 1;
      }

      // Create the runnable and execute
      EncryptQueryTask runEnc = new EncryptQueryTask(queryInfo.getDataPartitionBitSize(), paillier, selectorQueryVecMapping, start, stop);
      futures.add(es.submit(runEnc));
    }

    // Pull all encrypted elements and add to resultMap
    SortedMap<Integer,BigInteger> queryElements = new TreeMap<>();
    try
    {
      for (Future<SortedMap<Integer,BigInteger>> future : futures)
      {
        queryElements.putAll(future.get(1, TimeUnit.DAYS));
      }
    } catch (TimeoutException | ExecutionException e)
    {
      throw new PIRException("Exception in encryption threads.", e);
    }

    es.shutdown();

    return queryElements;
  }
}
