// Copyright 2019 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.android.resources;

import static com.google.common.base.Preconditions.checkState;

/** Denotes whether a resource is public/global or private/local. */
public enum Visibility {
  /**
   * Unknown/unspecified visibility. These are the legacy semantics used by both Bazel and Gradle.
   *
   * <p>Resources of all types in any given library may be accessed from dependents (via both XML
   * and Java R class constants). Resources may also be overriden by dependents, subject to
   * precedence rules.
   */
  UNKNOWN,

  /**
   * Public/global visibility. Identical semantics to {@link UNKNOWN}, though explicitly so via a
   * {@code <public>}; tag.
   */
  PUBLIC,

  /**
   * Private/local visibility. Implicitly specified by the absence of a {@code <public}; tag when
   * {@code <public>}; is used elsewhere in a library.
   *
   * <p>A true resource (everything except "id" and "styleable"). may not be accessed from
   * dependents via XML nor via Java outside of the resource's package. May not be overriden by
   * dependents. May not be made public by other libraries.
   *
   * <p>"styleable" does not represent a true resource (it doesn't exist in {@code resources.arsc}),
   * but rather serves to group {@code R.attr} values for custom view classes. Thus it is
   * permissible for multiple libraries to define different styleables with the same name, which
   * will have different package-private definitions in their respective R classes.
   *
   * <p>"id" normally does not represent a true resource, but generally is intended to map the ID's
   * name to an arbitrary number (generated by aapt2). It is permissible for multiple libraries to
   * declare the same ID, which will have identical package-private definitions in their respective
   * R classes.
   */
  PRIVATE;

  /** Merge visibility, to be used for "resources" such as R.id and R.styleable. */
  public static Visibility merge(Visibility v1, Visibility v2) {
    if (v1 == UNKNOWN || v2 == UNKNOWN) {
      return UNKNOWN;
    }
    if (v1 == PUBLIC || v2 == PUBLIC) {
      return PUBLIC;
    }
    checkState(v1 == PRIVATE && v2 == PRIVATE);
    return PRIVATE;
  }
}
