// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.server.contact;

import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.ContactInformation;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.rpc.ContactInformationStoreException;
import com.google.gerrit.server.UrlEncoded;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;

import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spearce.jgit.util.NB;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;

/** Encrypts {@link ContactInformation} instances and saves them. */
@Singleton
class EncryptedContactStore implements ContactStore {
  private static final Logger log =
      LoggerFactory.getLogger(EncryptedContactStore.class);
  private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

  private final SchemaFactory<ReviewDb> schema;
  private final PGPPublicKey dest;
  private final SecureRandom prng;
  private final URL storeUrl;
  private final String storeAPPSEC;

  EncryptedContactStore(final URL storeUrl, final String storeAPPSEC,
      final File pubKey, final SchemaFactory<ReviewDb> schema) {
    this.storeUrl = storeUrl;
    this.storeAPPSEC = storeAPPSEC;
    this.schema = schema;
    this.dest = selectKey(readPubRing(pubKey));

    final String prngName = "SHA1PRNG";
    try {
      prng = SecureRandom.getInstance(prngName);
    } catch (NoSuchAlgorithmException e) {
      throw new ProvisionException("Cannot create " + prngName, e);
    }

    // Run a test encryption to verify the proper algorithms exist in
    // our JVM and we are able to invoke them. This helps to identify
    // a system configuration problem early at startup, rather than a
    // lot later during runtime.
    //
    try {
      encrypt("test", new Date(0), "test".getBytes("UTF-8"));
    } catch (NoSuchProviderException e) {
      throw new ProvisionException("PGP encryption not available", e);
    } catch (PGPException e) {
      throw new ProvisionException("PGP encryption not available", e);
    } catch (IOException e) {
      throw new ProvisionException("PGP encryption not available", e);
    }
  }

  @Override
  public boolean isEnabled() {
    return true;
  }

  private static PGPPublicKeyRingCollection readPubRing(final File pub) {
    try {
      InputStream in = new FileInputStream(pub);
      try {
        in = PGPUtil.getDecoderStream(in);
        return new PGPPublicKeyRingCollection(in);
      } finally {
        in.close();
      }
    } catch (IOException e) {
      throw new ProvisionException("Cannot read " + pub, e);
    } catch (PGPException e) {
      throw new ProvisionException("Cannot read " + pub, e);
    }
  }

  private static PGPPublicKey selectKey(final PGPPublicKeyRingCollection rings) {
    for (final Iterator<?> ri = rings.getKeyRings(); ri.hasNext();) {
      final PGPPublicKeyRing currRing = (PGPPublicKeyRing) ri.next();
      for (final Iterator<?> ki = currRing.getPublicKeys(); ki.hasNext();) {
        final PGPPublicKey k = (PGPPublicKey) ki.next();
        if (k.isEncryptionKey()) {
          return k;
        }
      }
    }
    return null;
  }

  public void store(final Account account, final ContactInformation info)
      throws ContactInformationStoreException {
    try {
      final byte[] plainText = format(account, info).getBytes("UTF-8");
      final String fileName = "account-" + account.getId();
      final Date fileDate = account.getContactFiledOn();
      final byte[] encText = encrypt(fileName, fileDate, plainText);
      final String encStr = new String(encText, "UTF-8");

      final Timestamp filedOn = account.getContactFiledOn();
      final UrlEncoded u = new UrlEncoded();
      if (storeAPPSEC != null) {
        u.put("APPSEC", storeAPPSEC);
      }
      if (account.getPreferredEmail() != null) {
        u.put("email", account.getPreferredEmail());
      }
      if (filedOn != null) {
        u.put("filed", String.valueOf(filedOn.getTime() / 1000L));
      }
      u.put("account_id", String.valueOf(account.getId().get()));
      u.put("data", encStr);
      final byte[] body = u.toString().getBytes("UTF-8");

      final HttpURLConnection c = (HttpURLConnection) storeUrl.openConnection();
      c.setRequestMethod("POST");
      c.setRequestProperty("Content-Type",
          "application/x-www-form-urlencoded; charset=UTF-8");
      c.setDoOutput(true);
      c.setFixedLengthStreamingMode(body.length);
      final OutputStream out = c.getOutputStream();
      out.write(body);
      out.close();

      if (c.getResponseCode() == 200) {
        final byte[] dst = new byte[2];
        final InputStream in = c.getInputStream();
        try {
          NB.readFully(in, dst, 0, 2);
        } finally {
          in.close();
        }
        if (dst[0] != 'O' || dst[1] != 'K') {
          throw new IOException("Store failed: " + c.getResponseCode());
        }
      } else {
        throw new IOException("Store failed: " + c.getResponseCode());
      }

    } catch (IOException e) {
      log.error("Cannot store encrypted contact information", e);
      throw new ContactInformationStoreException(e);
    } catch (PGPException e) {
      log.error("Cannot store encrypted contact information", e);
      throw new ContactInformationStoreException(e);
    } catch (NoSuchProviderException e) {
      log.error("Cannot store encrypted contact information", e);
      throw new ContactInformationStoreException(e);
    }
  }

  private byte[] encrypt(final String name, final Date date,
      final byte[] rawText) throws NoSuchProviderException, PGPException,
      IOException {
    final byte[] zText = compress(name, date, rawText);
    final PGPEncryptedDataGenerator cpk =
        new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, true, prng, "BC");
    cpk.addMethod(dest);

    final ByteArrayOutputStream buf = new ByteArrayOutputStream();
    final ArmoredOutputStream aout = new ArmoredOutputStream(buf);
    final OutputStream cout = cpk.open(aout, zText.length);
    cout.write(zText);
    cout.close();
    aout.close();

    return buf.toByteArray();
  }

  private static byte[] compress(final String fileName, Date fileDate,
      final byte[] plainText) throws IOException {
    final ByteArrayOutputStream buf = new ByteArrayOutputStream();
    final PGPCompressedDataGenerator comdg;
    final int len = plainText.length;
    if (fileDate == null) {
      fileDate = PGPLiteralData.NOW;
    }

    comdg = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
    final OutputStream out =
        new PGPLiteralDataGenerator().open(comdg.open(buf),
            PGPLiteralData.BINARY, fileName, len, fileDate);
    out.write(plainText);
    out.close();
    comdg.close();
    return buf.toByteArray();
  }

  private String format(final Account account, final ContactInformation info)
      throws ContactInformationStoreException {
    Timestamp on = account.getContactFiledOn();
    if (on == null) {
      on = new Timestamp(System.currentTimeMillis());
    }

    final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    df.setTimeZone(UTC);

    final StringBuilder b = new StringBuilder();
    field(b, "Account-Id", account.getId().toString());
    field(b, "Date", df.format(on) + " " + UTC.getID());
    field(b, "Full-Name", account.getFullName());
    field(b, "Preferred-Email", account.getPreferredEmail());

    try {
      final ReviewDb db = schema.open();
      try {
        for (final AccountExternalId e : db.accountExternalIds().byAccount(
            account.getId())) {
          final StringBuilder oistr = new StringBuilder();
          if (e.getEmailAddress() != null && e.getEmailAddress().length() > 0) {
            if (oistr.length() > 0) {
              oistr.append(' ');
            }
            oistr.append(e.getEmailAddress());
          }
          if (e.isScheme(AccountExternalId.SCHEME_MAILTO)) {
            if (oistr.length() > 0) {
              oistr.append(' ');
            }
            oistr.append('<');
            oistr.append(e.getExternalId());
            oistr.append('>');
          }
          field(b, "Identity", oistr.toString());
        }
      } finally {
        db.close();
      }
    } catch (OrmException e) {
      throw new ContactInformationStoreException(e);
    }

    field(b, "Address", info.getAddress());
    field(b, "Country", info.getCountry());
    field(b, "Phone-Number", info.getPhoneNumber());
    field(b, "Fax-Number", info.getFaxNumber());
    return b.toString();
  }

  private static void field(final StringBuilder b, final String name,
      String value) {
    if (value == null) {
      return;
    }
    value = value.trim();
    if (value.length() == 0) {
      return;
    }

    b.append(name);
    b.append(':');
    if (value.indexOf('\n') == -1) {
      b.append(' ');
      b.append(value);
    } else {
      value = value.replaceAll("\r\n", "\n");
      value = value.replaceAll("\n", "\n\t");
      b.append("\n\t");
      b.append(value);
    }
    b.append('\n');
  }
}
