/*
 * 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;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.UUID;

import org.apache.pirk.encryption.Paillier;
import org.apache.pirk.querier.wideskies.decrypt.DecryptResponse;
import org.apache.pirk.querier.wideskies.encrypt.EncryptQuery;
import org.apache.pirk.query.wideskies.QueryInfo;
import org.apache.pirk.response.wideskies.Response;
import org.apache.pirk.schema.query.QuerySchemaRegistry;
import org.apache.pirk.serialization.LocalFileSystemStore;
import org.apache.pirk.utils.FileIOUtils;
import org.apache.pirk.utils.PIRException;
import org.apache.pirk.utils.SystemConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Driver class for encryption of a query or decryption of a response
 * <p>
 * File based: For encryption, specify:
 * <p>
 * (1) A query file - one selector per line and the first line in file is the unique query number,
 * <p>
 * (2) The query type, and
 * <p>
 * (3) All necessary encryption parameters.
 * <p>
 * Two corresponding files will be emitted:
 * <p>
 * (1) A file containing the serialized Query object (to be sent to the responder) and
 * <p>
 * (2) A file containing the serialized Querier object to be used for decryption.
 * <p>
 * For decryption, specify:
 * <p>
 * (1) A response file containing the serialized Response object and
 * <p>
 * (2) The corresponding decryption information file containing the serialized Querier object.
 * <p>
 * The output will be a file containing the hits for the query, where each line corresponds to one hit and is the string representation of the corresponding
 * QueryResponseJSON object.
 * <p>
 * Can optionally specify a bit position that must be set in the Paillier modulus
 * <p>
 * TODO:
 * <p>
 * - Add interior functionality for multiple query looping?
 * <p>
 * - Partition size is (practically) fixed at 8 bits, for now... configurable, but ignored right now
 */
public class QuerierDriver implements Serializable
{
  private static final long serialVersionUID = 1L;

  private static final Logger logger = LoggerFactory.getLogger(QuerierDriver.class);

  public static void main(String... args) throws IOException, InterruptedException, PIRException
  {
    // General variables
    String action;
    String inputFile;
    String outputFile;
    String queryType = null;
    int numThreads;
    LocalFileSystemStore storage = new LocalFileSystemStore();

    // Encryption variables
    int hashBitSize = 0;
    String hashKey = null;
    int dataPartitionBitSize = 0;
    int paillierBitSize = 0;
    int certainty = 0;
    int bitSet = -1;
    boolean embedSelector = true;
    boolean useMemLookupTable = false;
    boolean useHDFSLookupTable = false;

    // Decryption variables
    String querierFile = null;

    // Parse the args
    QuerierCLI qdriverCLI = new QuerierCLI(args);

    // Set the variables
    action = SystemConfiguration.getProperty(QuerierProps.ACTION);
    inputFile = SystemConfiguration.getProperty(QuerierProps.INPUTFILE);
    outputFile = SystemConfiguration.getProperty(QuerierProps.OUTPUTFILE);
    numThreads = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.NUMTHREADS));
    if (action.equals("encrypt"))
    {
      queryType = SystemConfiguration.getProperty(QuerierProps.QUERYTYPE);
      hashBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.HASHBITSIZE));
      hashKey = SystemConfiguration.getProperty(QuerierProps.HASHBITSIZE);
      dataPartitionBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.DATAPARTITIONSIZE));
      paillierBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.PAILLIERBITSIZE));
      certainty = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.CERTAINTY));
      embedSelector = SystemConfiguration.getBooleanProperty(QuerierProps.EMBEDSELECTOR, true);
      useMemLookupTable = SystemConfiguration.getBooleanProperty(QuerierProps.USEMEMLOOKUPTABLE, false);
      useHDFSLookupTable = SystemConfiguration.getBooleanProperty(QuerierProps.USEHDFSLOOKUPTABLE, false);

      if (SystemConfiguration.hasProperty(QuerierProps.BITSET))
      {
        bitSet = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.BITSET));
        logger.info("bitSet = " + bitSet);
      }

      // Check to ensure we have a valid queryType
      if (QuerySchemaRegistry.get(queryType) == null)
      {
        logger.error("Invalid schema: " + queryType + "; The following schemas are loaded:");
        for (String schema : QuerySchemaRegistry.getNames())
        {
          logger.info("schema = " + schema);
        }
        System.exit(0);
      }

      // Enforce dataPartitionBitSize < 32
      if (dataPartitionBitSize > 31)
      {
        logger.error("dataPartitionBitSize = " + dataPartitionBitSize + "; must be less than 32");
      }
    }
    if (action.equals("decrypt"))
    {
      querierFile = SystemConfiguration.getProperty(QuerierProps.QUERIERFILE);
    }

    // Perform the action
    if (action.equals("encrypt"))
    {
      logger.info("Performing encryption: \n inputFile = " + inputFile + "\n outputFile = " + outputFile + "\n numThreads = " + numThreads
          + "\n hashBitSize = " + hashBitSize + "\n hashKey = " + hashKey + "\n dataPartitionBitSize = " + dataPartitionBitSize + "\n paillierBitSize = "
          + paillierBitSize + "\n certainty = " + certainty);

      // Read in the selectors and extract the queryIdentifier - first line in the file
      ArrayList<String> selectors = FileIOUtils.readToArrayList(inputFile);
      UUID queryIdentifier = UUID.fromString(selectors.get(0));
      selectors.remove(0);

      int numSelectors = selectors.size();
      logger.info("queryIdentifier = " + queryIdentifier + " numSelectors = " + numSelectors);

      // Set the necessary QueryInfo and Paillier objects
      QueryInfo queryInfo = new QueryInfo(queryIdentifier, numSelectors, hashBitSize, hashKey, dataPartitionBitSize, queryType, useMemLookupTable,
          embedSelector, useHDFSLookupTable);

      if (SystemConfiguration.isSetTrue("pir.embedQuerySchema"))
      {
        queryInfo.addQuerySchema(QuerySchemaRegistry.get(queryType));
      }

      Paillier paillier = new Paillier(paillierBitSize, certainty, bitSet); // throws PIRException if certainty conditions are not satisfied

      // Check the number of selectors to ensure that 2^{numSelector*dataPartitionBitSize} < N
      // For example, if the highest bit is set, the largest value is \floor{paillierBitSize/dataPartitionBitSize}
      int exp = numSelectors * dataPartitionBitSize;
      BigInteger val = (BigInteger.valueOf(2)).pow(exp);
      if (val.compareTo(paillier.getN()) != -1)
      {
        logger.error("The number of selectors = " + numSelectors + " must be such that " + "2^{numSelector*dataPartitionBitSize} < N = "
            + paillier.getN().toString(2));
        System.exit(0);
      }

      // Perform the encryption
      EncryptQuery encryptQuery = new EncryptQuery(queryInfo, selectors, paillier);
      encryptQuery.encrypt(numThreads);

      // Write necessary output files - two files written -
      // (1) Querier object to <outputFile>-QuerierConst.QUERIER_FILETAG
      // (2) Query object to <outputFile>-QuerierConst.QUERY_FILETAG
      storage.store(outputFile + "-" + QuerierConst.QUERIER_FILETAG, encryptQuery.getQuerier());
      storage.store(outputFile + "-" + QuerierConst.QUERY_FILETAG, encryptQuery.getQuery());
    }
    else
    // Decryption
    {
      // Reconstruct the necessary objects from the files
      Response response = storage.recall(inputFile, Response.class);
      Querier querier = storage.recall(querierFile, Querier.class);

      UUID querierQueryID = querier.getQuery().getQueryInfo().getIdentifier();
      UUID responseQueryID = response.getQueryInfo().getIdentifier();
      if (!querierQueryID.equals(responseQueryID))
      {
        logger.error("The query identifier in the Response: " + responseQueryID.toString() + " does not match the query identifier specified in the Querier: "
            + querierQueryID.toString());
        System.exit(0);
      }

      // Perform decryption and output the result file
      DecryptResponse decryptResponse = new DecryptResponse(response, querier);
      decryptResponse.decrypt(numThreads);
      decryptResponse.writeResultFile(outputFile);
    }
  }
}
