// Copyright 2014 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.lib.util;

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import java.util.Map;

/**
 * A string indexer backed by a map and reverse index lookup.
 * Every unique string is stored in memory exactly once.
 */
@ThreadSafe
public class CanonicalStringIndexer extends AbstractIndexer {

  private static final int NOT_FOUND = -1;

  // This is similar to (Synchronized) BiMap.
  // These maps *must* be weakly threadsafe to ensure thread safety for string
  // indexer as a whole. Specifically, mutating operations are serialized, but
  // read-only operations may be executed concurrently with mutators.
  private final Map<String, Integer> stringToInt;
  private final Map<Integer, String> intToString;

  /*
   * Creates an indexer instance from two backing maps. These maps may be
   * pre-initialized with data, but *must*:
   * a. Support read-only operations done concurrently with mutations.
   *    Note that mutations will be serialized.
   * b. Be reverse mappings of each other, if pre-initialized.
   */
  public CanonicalStringIndexer(Map<String, Integer> stringToInt,
                                Map<Integer, String> intToString) {
    Preconditions.checkArgument(stringToInt.size() == intToString.size());
    this.stringToInt = stringToInt;
    this.intToString = intToString;
  }


  @Override
  public synchronized void clear() {
    stringToInt.clear();
    intToString.clear();
  }

  @Override
  public int size() {
    return intToString.size();
  }

  @Override
  public int getOrCreateIndex(String s) {
    Integer i = stringToInt.get(s);
    if (i == null) {
      s = StringCanonicalizer.intern(s);
      synchronized (this) {
        // First, make sure another thread hasn't just added the entry:
        i = stringToInt.get(s);
        if (i != null) {
          return i;
        }

        int ind = intToString.size();
        stringToInt.put(s, ind);
        intToString.put(ind, s);
        return ind;
      }
    } else {
      return i;
    }
  }

  @Override
  public int getIndex(String s) {
    Integer i = stringToInt.get(s);
    return (i == null) ? NOT_FOUND : i;
  }

  @Override
  public String getStringForIndex(int i) {
    return intToString.get(i);
  }

  @Override
  public synchronized String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("size = ").append(size()).append("\n");
    for (Map.Entry<String, Integer> entry : stringToInt.entrySet()) {
      builder.append(entry.getKey()).append(" <==> ").append(entry.getValue()).append("\n");
    }
    return builder.toString();
  }
}
