content: package im.actor.core.modules.encryption.entity;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
  
  import im.actor.core.util.RandomUtils;
  import im.actor.runtime.bser.BserObject;
  import im.actor.runtime.bser.BserValues;
  import im.actor.runtime.bser.BserWriter;
  
  public class PrivateKeyStorage extends BserObject {
  
      private int keyGroupId;
      private PrivateKey identityKey = null;
      private PrivateKey[] keys;
      private PrivateKey[] preKeys;
      private boolean wasRegenerated = false;
  
      public PrivateKeyStorage(int keyGroupId, PrivateKey identityKey, PrivateKey[] keys, PrivateKey[] preKeys) {
          this.keyGroupId = keyGroupId;
          this.identityKey = identityKey;
          this.keys = keys;
          this.preKeys = preKeys;
      }
  
      public PrivateKeyStorage(byte[] data) throws IOException {
          load(data);
      }
  
      public int getKeyGroupId() {
          return keyGroupId;
      }
  
      public PrivateKey getIdentityKey() {
          return identityKey;
      }
  
      public PrivateKey[] getKeys() {
          return keys;
      }
  
      public PrivateKeyStorage setGroupId(int groupId) {
          return new PrivateKeyStorage(groupId, identityKey, keys, preKeys);
      }
  
      public PrivateKeyStorage appendPreKeys(PrivateKey[] addedPreKeys) {
          PrivateKey[] nKeys = new PrivateKey[
                  addedPreKeys.length + preKeys.length];
          System.arraycopy(preKeys, 0, nKeys, 0, preKeys.length);
          System.arraycopy(addedPreKeys, 0, nKeys, preKeys.length, addedPreKeys.length);
          return new PrivateKeyStorage(keyGroupId, identityKey, keys, nKeys);
      }
  
      public PrivateKeyStorage markAsUploaded(PrivateKey[] uploadedPreKeys) {
          PrivateKey[] nKeys = new PrivateKey[preKeys.length];
          for (int i = 0; i < preKeys.length; i++) {
              boolean found = false;
              for (int j = 0; j < uploadedPreKeys.length; j++) {
                  if (uploadedPreKeys[j].getKeyId() == preKeys[i].getKeyId()) {
                      found = true;
                      break;
                  }
              }
              if (found) {
                  nKeys[i] = preKeys[i].markAsUploaded();
              } else {
                  nKeys[i] = preKeys[i];
              }
          }
          return new PrivateKeyStorage(keyGroupId, identityKey, keys, nKeys);
      }
  
      public PrivateKey[] getPreKeys() {
          return preKeys;
      }
  
      public PrivateKey pickRandomPreKey() {
          ArrayList<PrivateKey> uploadedKeys = new ArrayList<PrivateKey>();
          for (PrivateKey u : preKeys) {
              if (u.isUploaded()) {
                  uploadedKeys.add(u);
              }
          }
          return uploadedKeys.get(RandomUtils.randomId(uploadedKeys.size()));
      }
  
      public boolean isWasRegenerated() {
          return wasRegenerated;
      }
  
      @Override
      public void parse(BserValues values) throws IOException {
          keyGroupId = values.getInt(1);
          identityKey = new PrivateKey(values.getBytes(2));
          wasRegenerated |= identityKey.isWasRegenerated();
          List<byte[]> r = values.getRepeatedBytes(3);
          keys = new PrivateKey[r.size()];
          for (int i = 0; i < keys.length; i++) {
              keys[i] = new PrivateKey(r.get(i));
              wasRegenerated |= keys[i].isWasRegenerated();
          }
          r = values.getRepeatedBytes(4);
          preKeys = new PrivateKey[r.size()];
          for (int i = 0; i < preKeys.length; i++) {
              preKeys[i] = new PrivateKey(r.get(i));
              wasRegenerated |= preKeys[i].isWasRegenerated();
          }
      }
  
      @Override
      public void serialize(BserWriter writer) throws IOException {
          writer.writeInt(1, keyGroupId);
          writer.writeBytes(2, identityKey.toByteArray());
          for (PrivateKey k : keys) {
              writer.writeBytes(3, k.toByteArray());
          }
          for (PrivateKey k : preKeys) {
              writer.writeBytes(4, k.toByteArray());
          }
      }
  }
  