package org.robolectric.res;

import java.util.*;

public class ResBundle {
  private final ResMap valuesMap = new ResMap();

  public void put(String attrType, String name, TypedResource value) {
    XmlLoader.XmlContext xmlContext = value.getXmlContext();
    ResName resName = new ResName(xmlContext.getPackageName(), attrType, name);
    valuesMap.put(resName, value);
  }

  public TypedResource get(ResName resName, String qualifiers) {
    return valuesMap.pick(resName, qualifiers);
  }

  public void receive(ResourceTable.Visitor visitor) {
    for (final Map.Entry<ResName, Map<String, TypedResource>> entry : valuesMap.map.entrySet()) {
      visitor.visit(entry.getKey(), entry.getValue().values());
    }
  }

  public static class Value<T> implements Comparable<Value<T>> {
    private final String qualifiers;
    private final T value;

    Value(String qualifiers, T value) {
      if (value == null) {
        throw new NullPointerException();
      }

      this.qualifiers = qualifiers == null ? "--" : "-" + qualifiers + "-";
      this.value = value;
    }

    public String getQualifiers() {
      return qualifiers;
    }

    public T getValue() {
      return value;
    }

    @Override
    public int compareTo(Value<T> o) {
      return qualifiers.compareTo(o.qualifiers);
    }

    @Override public String toString() {
      return "Value{" +
          "qualifiers='" + qualifiers + '\'' +
          ", value=" + value +
          '}';
    }
  }

  static class ResMap {
    private final Map<ResName, Map<String, TypedResource>> map = new HashMap<>();

    public TypedResource pick(ResName resName, String qualifiersStr) {
      Map<String, TypedResource> values = map.get(resName);
      if (values == null || values.size() == 0) return null;

      TreeSet<TypedResource> typedResources = new TreeSet<>(new QualifierSort());
      typedResources.addAll(values.values());

      // This should really follow the android algorithm specified at:
      // http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch
      //
      // 1: eliminate resources that contradict the qualifiersStr
      // 2: pick the (next) highest-precedence qualifier type in "table 2" of the reference above
      // 3: check if any resource values use this qualifier, if no, back to 2, else move on to 4.
      // 4: eliminate resources values that don't use this qualifier.
      // 5: if more than one resource is left, go back to 2.
      //
      // However, we currently only model the smallest/available width/height and version qualifiers
      // rather than all of the possibly qualifier classes in table 2.

      Qualifiers toMatch = Qualifiers.parse(qualifiersStr);

      List<TypedResource> passesRequirements = new ArrayList<>();
      for (TypedResource candidate : typedResources) {
        Qualifiers qualifiers = Qualifiers.parse(candidate.getQualifiers());
        if (qualifiers.passesRequirements(toMatch)) {
          passesRequirements.add(candidate);
        }
      }

      Qualifiers bestMatchQualifiers = null;
      TypedResource bestMatch = null;
      for (TypedResource candidate : passesRequirements) {
        Qualifiers qualifiers = Qualifiers.parse(candidate.getQualifiers());
        if (qualifiers.matches(toMatch)) {
          if (bestMatchQualifiers == null || qualifiers.isBetterThan(bestMatchQualifiers, toMatch)) {
            bestMatchQualifiers = qualifiers;
            bestMatch =  candidate;
          }
        }
      }
      if (bestMatch != null) {
        return bestMatch;
      }
      if (!passesRequirements.isEmpty()) {
        return passesRequirements.get(0);
      }
      return null;
    }

    public void put(ResName resName, TypedResource value) {
      Map<String, TypedResource> values = map.get(resName);
      if (values == null) map.put(resName, values = new HashMap<>());
      if (!values.containsKey(value.getQualifiers())) {
        values.put(value.getQualifiers(), value);
      }
    }

    public int size() {
      return map.size();
    }

    public static class QualifierSort implements Comparator<TypedResource> {
      @Override
      public int compare(TypedResource o1, TypedResource o2) {
        return o1.getQualifiers().compareTo(o2.getQualifiers());
      }
    }
  }
}

@@ -721,764 +721,8 @@
  %7D%0A%0A
-  public static class Value%3CT%3E implements Comparable%3CValue%3CT%3E%3E %7B%0A    private final String qualifiers;%0A    private final T value;%0A%0A    Value(String qualifiers, T value) %7B%0A      if (value == null) %7B%0A        throw new NullPointerException();%0A      %7D%0A%0A      this.qualifiers = qualifiers == null ? %22--%22 : %22-%22 + qualifiers + %22-%22;%0A      this.value = value;%0A    %7D%0A%0A    public String getQualifiers() %7B%0A      return qualifiers;%0A    %7D%0A%0A    public T getValue() %7B%0A      return value;%0A    %7D%0A%0A    @Override%0A    public int compareTo(Value%3CT%3E o) %7B%0A      return qualifiers.compareTo(o.qualifiers);%0A    %7D%0A%0A    @Override public String toString() %7B%0A      return %22Value%7B%22 +%0A          %22qualifiers='%22 + qualifiers + '%5C'' +%0A          %22, value=%22 + value +%0A          '%7D';%0A    %7D%0A  %7D%0A%0A
   st

Remove dead code.