content: /*
   * Copyright (C) 2015 Actor LLC. <https://actor.im>
   */
  
  package im.actor.runtime.js.storage;
  
  import com.google.gwt.storage.client.Storage;
  
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import im.actor.runtime.Log;
  import im.actor.runtime.bser.DataInput;
  import im.actor.runtime.bser.DataOutput;
  import im.actor.runtime.storage.KeyValueRecord;
  import im.actor.runtime.storage.KeyValueStorage;
  
  import static im.actor.runtime.crypto.Base64Utils.fromBase64;
  import static im.actor.runtime.crypto.Base64Utils.toBase64;
  
  public class JsKeyValueStorage implements KeyValueStorage {
  
      private static final String TAG = "JsKeyValueStorage";
  
      private Storage storage;
      private String prefix;
      private Set<Long> items = new HashSet<Long>();
  
      public JsKeyValueStorage(String prefix, Storage storage) {
          this.storage = storage;
          this.prefix = prefix;
  
          try {
              String index = storage.getItem("kv_" + prefix + "_index");
              if (index != null) {
                  byte[] data = fromBase64(index);
                  DataInput dataInput = new DataInput(data, 0, data.length);
                  int count = dataInput.readInt();
                  for (int i = 0; i < count; i++) {
                      items.add(dataInput.readLong());
                  }
              }
          } catch (Exception e) {
              Log.e(TAG, e);
          }
      }
  
      @Override
      public void addOrUpdateItem(long id, byte[] data) {
          storage.setItem(getId(id), toBase64(data));
  
          if (!items.contains(id)) {
              items.add(id);
              saveIndex();
          }
      }
  
      @Override
      public void addOrUpdateItems(List<KeyValueRecord> values) {
          boolean isAdded = false;
          for (KeyValueRecord record : values) {
              long id = record.getId();
              storage.setItem(getId(id), toBase64(record.getData()));
  
              if (!items.contains(id)) {
                  items.add(id);
                  isAdded = true;
              }
          }
          if (isAdded) {
              saveIndex();
          }
      }
  
      @Override
      public void removeItem(long id) {
          if (!items.contains(id)) {
              return;
          }
          storage.removeItem(getId(id));
          items.remove(id);
          saveIndex();
      }
  
      @Override
      public void removeItems(long[] ids) {
          boolean isRemoved = false;
          for (long id : ids) {
              if (items.contains(id)) {
                  storage.removeItem(getId(id));
                  items.remove(id);
                  isRemoved = true;
              }
          }
          if (isRemoved) {
              saveIndex();
          }
      }
  
      @Override
      public byte[] loadItem(long key) {
          String res = storage.getItem(getId(key));
          if (res == null) {
              return null;
          } else {
              return fromBase64(res);
          }
      }
  
      @Override
      public List<KeyValueRecord> loadItems(long[] keys) {
          // TODO: Implement
          return null;
      }
  
      @Override
      public List<KeyValueRecord> loadAllItems() {
          // TODO: Implement
          return null;
      }
  
      @Override
      public void clear() {
          for (long id : items) {
              storage.removeItem(getId(id));
          }
          storage.removeItem("kv_" + prefix + "_index");
          items.clear();
      }
  
      private void saveIndex() {
          DataOutput dataOutput = new DataOutput();
          dataOutput.writeInt(items.size());
          for (long l : items) {
              dataOutput.writeLong(l);
          }
          storage.setItem("kv_" + prefix + "_index", toBase64(dataOutput.toByteArray()));
      }
  
      private String getId(long id) {
          return "kv_" + prefix + "_" + id;
      }
  }
  