/*
 * Copyright 2014-present Facebook, Inc.
 *
 * 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.facebook.buck.android.aapt;

import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.MoreStrings;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.FluentIterable;

import java.io.IOException;
import java.nio.file.Path;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** Represents a row from a symbols file generated by {@code aapt}. */
public class RDotTxtEntry implements Comparable<RDotTxtEntry> {

  // Taken from http://developer.android.com/reference/android/R.html
  public static enum RType {
    ANIM,
    ANIMATOR,
    ARRAY,
    ATTR,
    BOOL,
    COLOR,
    DIMEN,
    DRAWABLE,
    FRACTION,
    ID,
    INTEGER,
    INTERPOLATOR,
    LAYOUT,
    MENU,
    MIPMAP,
    PLURALS,
    RAW,
    STRING,
    STYLE,
    STYLEABLE,
    XML;

    @Override
    public String toString() {
      return super.toString().toLowerCase();
    }
  }

  public static enum IdType {
    INT,
    INT_ARRAY;

    public static IdType from(String raw) {
      if (raw.equals("int")) {
        return INT;
      } else if (raw.equals("int[]")) {
        return INT_ARRAY;
      }
      throw new IllegalArgumentException(String.format("'%s' is not a valid ID type.", raw));
    }

    @Override
    public String toString() {
      if (this.equals(INT)) {
        return "int";
      }
      return "int[]";
    }
  }

  public static final Function<String, RDotTxtEntry> TO_ENTRY =
      new Function<String, RDotTxtEntry>() {
        @Override
        public RDotTxtEntry apply(String input) {
          Optional<RDotTxtEntry> entry = parse(input);
          Preconditions.checkNotNull(entry.isPresent(), "Could not parse R.txt entry: '%s'", input);
          return entry.get();
        }
      };

  private static final Pattern TEXT_SYMBOLS_LINE = Pattern.compile("(\\S+) (\\S+) (\\S+) (.+)");

  // A symbols file may look like:
  //
  //    int id placeholder 0x7f020000
  //    int string debug_http_proxy_dialog_title 0x7f030004
  //    int string debug_http_proxy_hint 0x7f030005
  //    int string debug_http_proxy_summary 0x7f030003
  //    int string debug_http_proxy_title 0x7f030002
  //    int string debug_ssl_cert_check_summary 0x7f030001
  //    int string debug_ssl_cert_check_title 0x7f030000
  //
  // Note that there are four columns of information:
  // - the type of the resource id (always seems to be int or int[], in practice)
  // - the type of the resource
  // - the name of the resource
  // - the value of the resource id
  public final IdType idType;
  public final RType type;
  public final String name;
  public final String idValue;

  public RDotTxtEntry(
      IdType idType,
      RType type,
      String name,
      String idValue) {
    this.idType = idType;
    this.type = type;
    this.name = name;
    this.idValue = idValue;
  }

  public RDotTxtEntry copyWithNewIdValue(String newIdValue) {
    return new RDotTxtEntry(idType, type, name, newIdValue);
  }

  public static Optional<RDotTxtEntry> parse(String rDotTxtLine) {
    Matcher matcher = TEXT_SYMBOLS_LINE.matcher(rDotTxtLine);
    if (!matcher.matches()) {
      return Optional.absent();
    }

    IdType idType = IdType.from(matcher.group(1));
    RType type = RType.valueOf(matcher.group(2).toUpperCase());
    String name = matcher.group(3);
    String idValue = matcher.group(4);

    return Optional.of(new RDotTxtEntry(idType, type, name, idValue));
  }

  public static Iterable<RDotTxtEntry> readResources(ExecutionContext context, Path rDotTxt)
      throws IOException {
    return FluentIterable.from(context.getProjectFilesystem().readLines(rDotTxt))
        .filter(MoreStrings.NON_EMPTY)
        .transform(RDotTxtEntry.TO_ENTRY);
  }

  /**
   * A collection of Resources should be sorted such that Resources of the same type should be
   * grouped together, and should be alphabetized within that group.
   */
  @Override
  public int compareTo(RDotTxtEntry that) {
    return ComparisonChain.start()
        .compare(this.type, that.type)
        .compare(this.name, that.name)
        .result();
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof RDotTxtEntry)) {
      return false;
    }

    RDotTxtEntry that = (RDotTxtEntry) obj;
    return Objects.equal(this.type, that.type) && Objects.equal(this.name, that.name);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(type, name);
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(RDotTxtEntry.class)
        .add("idType", idType)
        .add("type", type)
        .add("name", name)
        .add("idValue", idValue)
        .toString();
  }
}

@@ -2471,15 +2471,13 @@
 heck
-NotNull
+State
 (ent

Fix wrong precondition check.