package org.robolectric.res;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

public class PackageResourceIndex implements ResourceIndex {
  private static final Logger LOGGER = Logger.getLogger(ResourceExtractor.class.getName());

  private final BiMap<Integer, ResName> resourceTable = HashBiMap.create();

  private Integer maxUsedInt = null;
  private Integer generatedIdStart = null;
  private String packageName;
  private int packageIdentifier;

  public PackageResourceIndex(String packageName) {
    this.packageName = packageName;
  }

  @Override
  public synchronized Integer getResourceId(ResName resName) {
    Integer id = resourceTable.inverse().get(resName);
    if (id == null && ("android".equals(resName.packageName) || "".equals(resName.packageName))) {
      if (maxUsedInt == null) {
        maxUsedInt = resourceTable.isEmpty() ? 0 : Collections.max(resourceTable.keySet());
        generatedIdStart = maxUsedInt;
      }
      id = ++maxUsedInt;
      resourceTable.put(id, resName);
      LOGGER.fine("no id mapping found for " + resName.getFullyQualifiedName() + "; assigning ID #0x" + Integer.toHexString(id));
    }
    if (id == null) return 0;

    return id;
  }

  @Override
  public synchronized ResName getResName(int resourceId) {
    return resourceTable.get(resourceId);
  }

  @Override
  public void dump() {
    System.out.println(resourceTable);
  }

  public String getPackageName() {
    return packageName;
  }

  int getPackageIdentifier() {
    return packageIdentifier;
  }

  void addResource(int id, String type, String name) {
    ResName resName = new ResName(packageName, type, name);
    int resIdPackageIdentifier = ResourceIds.getPackageIdentifier(id);
    if (getPackageIdentifier() == 0) {
      this.packageIdentifier = resIdPackageIdentifier;
    } else if (getPackageIdentifier() != resIdPackageIdentifier) {
      throw new IllegalArgumentException("Attempted to add resId " + resIdPackageIdentifier + " to PackageResourceIndex with packageIdentifier " + getPackageIdentifier());
    }

    ResName existingEntry = resourceTable.put(id, resName);
    if (existingEntry != null && !existingEntry.equals(resName)) {
      throw new IllegalArgumentException("ResId " + Integer.toHexString(id) + " mapped to both " + resName + " and " + existingEntry);
    }
  }
}

@@ -465,76 +465,92 @@
 ate 
-Integer maxUsedInt = null;%0A  private Integer generatedIdStart = null
+final ResourceIdGenerator androidResourceIdGenerator = new ResourceIdGenerator(0x01)
 ;%0A  
@@ -557,16 +557,22 @@
 private 
+final 
 String p
@@ -866,279 +866,111 @@
  && 
-(%22a
+isA
 ndroid
-%22.equals(resName.packageName) %7C%7C %22%22.equals(resName.packageName))) %7B%0A      if (maxUsedInt == null) %7B%0A        maxUsedInt = resourceTable.isEmpty() ? 0 : Collections.max(resourceTable.keySet());%0A        generatedIdStart = maxUsedInt;%0A      %7D%0A      id = ++maxUsedInt
+Package(resName)) %7B%0A      id = androidResourceIdGenerator.generate(resName.type, resName.name)
 ;%0A  
@@ -1188,24 +1188,167 @@
 rn id;%0A  %7D%0A%0A
+  private boolean isAndroidPackage(ResName resName) %7B%0A    return %22android%22.equals(resName.packageName) %7C%7C %22%22.equals(resName.packageName);%0A  %7D%0A%0A
   @Override%0A
@@ -1474,16 +1474,29 @@
  public 
+synchronized 
 void dum
@@ -1677,16 +1677,29 @@
 %0A  %7D%0A%0A  
+synchronized 
 void add
@@ -1739,24 +1739,134 @@
 ing name) %7B%0A
+    if (ResourceIds.isFrameworkResource(id)) %7B%0A      androidResourceIdGenerator.record(id, type, name);%0A    %7D%0A
     ResName 

Use ResourceIdGenerator for missing Android IDs in PackageResourceIndex. This will be refactored again in the future to generate the IDs as the XML files are being processed and the resources loaded into the index.