// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;

import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

class MethodNamingState<KeyType> {

  private final MethodNamingState<KeyType> parent;
  private final Map<KeyType, InternalReservationState> usedNames = new HashMap<>();
  private final Map<KeyType, InternalNewNameState> newNameStates = new HashMap<>();
  private final Function<DexProto, KeyType> keyTransform;
  private final MemberNamingStrategy strategy;

  static <S> MethodNamingState<S> createRoot(
      Function<DexProto, S> keyTransform, MemberNamingStrategy strategy) {
    return new MethodNamingState<>(null, keyTransform, strategy);
  }

  private MethodNamingState(
      MethodNamingState<KeyType> parent,
      Function<DexProto, KeyType> keyTransform,
      MemberNamingStrategy strategy) {
    this.parent = parent;
    this.keyTransform = keyTransform;
    this.strategy = strategy;
  }

  MethodNamingState<KeyType> createChild() {
    return new MethodNamingState<>(this, keyTransform, strategy);
  }

  private InternalReservationState findInternalReservationStateFor(KeyType key) {
    InternalReservationState result = usedNames.get(key);
    if (result == null && parent != null) {
      result = parent.findInternalReservationStateFor(key);
    }
    return result;
  }

  private InternalReservationState getOrCreateInternalReservationStateFor(KeyType key) {
    InternalReservationState result = usedNames.get(key);
    if (result == null) {
      InternalReservationState parentState =
          parent != null ? parent.getOrCreateInternalReservationStateFor(key) : null;
      result = new InternalReservationState(parentState);
      usedNames.put(key, result);
    }
    return result;
  }

  private InternalNewNameState findInternalNewNameStateFor(KeyType key) {
    InternalNewNameState result = newNameStates.get(key);
    if (result == null && parent != null) {
      result = parent.findInternalNewNameStateFor(key);
    }
    return result;
  }

  private InternalNewNameState getOrCreateNewNameStateFor(KeyType key) {
    InternalNewNameState result = newNameStates.get(key);
    if (result == null) {
      InternalReservationState reservationState = getOrCreateInternalReservationStateFor(key);
      assert reservationState != null;
      InternalNewNameState parentState =
          parent != null ? parent.getOrCreateNewNameStateFor(key) : null;
      result = new InternalNewNameState(parentState, reservationState);
      newNameStates.put(key, result);
    }
    return result;
  }

  private DexString getAssignedNameFor(DexString name, KeyType key) {
    InternalReservationState state = findInternalReservationStateFor(key);
    if (state == null) {
      return null;
    }
    return state.getAssignedNameFor(name);
  }

  DexString assignNewNameFor(DexMethod source, DexString original, DexProto proto) {
    KeyType key = keyTransform.apply(proto);
    DexString result = getAssignedNameFor(original, key);
    if (result == null) {
      InternalNewNameState state = getOrCreateNewNameStateFor(key);
      result = state.getNewNameFor(source);
    }
    return result;
  }

  void reserveName(DexString name, DexProto proto, DexString originalName) {
    KeyType key = keyTransform.apply(proto);
    InternalReservationState state = getOrCreateInternalReservationStateFor(key);
    state.reserveName(name, originalName);
  }

  boolean isReserved(DexString name, DexProto proto) {
    KeyType key = keyTransform.apply(proto);
    InternalReservationState state = findInternalReservationStateFor(key);
    if (state == null) {
      return false;
    }
    return state.isReserved(name);
  }

  DexString getReservedOriginalName(DexString name, DexProto proto) {
    KeyType key = keyTransform.apply(proto);
    InternalReservationState state = findInternalReservationStateFor(key);
    if (state == null) {
      return null;
    }
    return state.getReservedOriginalName(name);
  }

  boolean isAvailable(DexProto proto, DexString candidate) {
    KeyType key = keyTransform.apply(proto);
    InternalReservationState state = findInternalReservationStateFor(key);
    if (state == null) {
      return true;
    }
    return state.isAvailable(candidate);
  }

  void addRenaming(DexString original, DexProto proto, DexString newName) {
    KeyType key = keyTransform.apply(proto);
    InternalReservationState state = getOrCreateInternalReservationStateFor(key);
    state.addRenaming(original, newName);
  }

  void printState(
      DexProto proto,
      Function<MethodNamingState<?>, DexType> stateKeyGetter,
      String indentation,
      PrintStream out) {
    KeyType key = keyTransform.apply(proto);
    InternalNewNameState state = getOrCreateNewNameStateFor(key);
    out.print(indentation);
    out.print("NamingState(node=`");
    out.print(stateKeyGetter.apply(this).toSourceString());
    out.print("`, proto=`");
    out.print(proto.toSourceString());
    out.print("`, key=`");
    out.print(key.toString());
    out.println("`)");
    if (state != null) {
      state.printInternalState(this, stateKeyGetter, indentation + "  ", out);
    } else {
      out.print(indentation);
      out.println("<NO STATE>");
    }
  }

  class InternalReservationState {
    private final InternalReservationState parentInternalState;
    private Map<DexString, DexString> reservedNames = null;
    private Map<DexString, DexString> renamings = null;

    private InternalReservationState(InternalReservationState parentInternalState) {
      this.parentInternalState = parentInternalState;
    }

    boolean isReserved(DexString name) {
      return (reservedNames != null && reservedNames.containsKey(name))
          || (parentInternalState != null && parentInternalState.isReserved(name));
    }

    DexString getReservedOriginalName(DexString name) {
      DexString result = null;
      if (reservedNames != null) {
        result = reservedNames.get(name);
      }
      if (result == null && parentInternalState != null) {
        result = parentInternalState.getReservedOriginalName(name);
      }
      return result;
    }

    DexString getAssignedNameFor(DexString original) {
      DexString result = null;
      if (renamings != null) {
        result = renamings.get(original);
      }
      if (result == null && parentInternalState != null) {
        result = parentInternalState.getAssignedNameFor(original);
      }
      return result;
    }

    private boolean isAvailable(DexString name) {
      return !(renamings != null && renamings.containsValue(name))
          && !(reservedNames != null && reservedNames.containsKey(name))
          && (parentInternalState == null || parentInternalState.isAvailable(name));
    }

    void reserveName(DexString name, DexString originalName) {
      if (reservedNames == null) {
        reservedNames = new HashMap<>();
      }
      reservedNames.put(name, originalName);
    }

    void addRenaming(DexString original, DexString newName) {
      if (renamings == null) {
        renamings = new HashMap<>();
      }
      renamings.put(original, newName);
    }

    void printReservedNames(String indentation, PrintStream out) {
      out.print(indentation);
      out.print("Reserved names:");
      if (reservedNames == null || reservedNames.isEmpty()) {
        out.print(" <NO RESERVED NAMES>");
      } else {
        for (DexString reservedName : reservedNames.keySet()) {
          out.print(System.lineSeparator());
          out.print(indentation);
          out.print("  ");
          out.print(reservedName.toSourceString() + "(by " + reservedNames.get(reservedName) + ")");
        }
      }
      out.println();
    }

    void printRenamings(String indentation, PrintStream out) {
      out.print(indentation);
      out.print("Renamings:");
      if (renamings == null || renamings.isEmpty()) {
        out.print(" <NO RENAMINGS>");
      } else {
        for (DexString original : renamings.keySet()) {
          out.print(System.lineSeparator());
          out.print(indentation);
          out.print("  ");
          out.print(original.toSourceString());
          out.print(" -> ");
          out.print(renamings.get(original).toSourceString());
        }
      }
      out.println();
    }
  }

  class InternalNewNameState implements InternalNamingState {

    private final InternalNewNameState parentInternalState;
    private final InternalReservationState reservationState;
    private final Predicate<DexString> isUsed;

    private static final int INITIAL_NAME_COUNT = 1;
    private static final int INITIAL_DICTIONARY_INDEX = 0;

    private int virtualNameCount;
    private int directNameCount = 0;
    private int dictionaryIndex;

    private InternalNewNameState(
        InternalNewNameState parentInternalState, InternalReservationState reservationState) {
      this.parentInternalState = parentInternalState;
      this.reservationState = reservationState;
      this.dictionaryIndex =
          parentInternalState == null
              ? INITIAL_DICTIONARY_INDEX
              : parentInternalState.dictionaryIndex;
      this.virtualNameCount =
          parentInternalState == null ? INITIAL_NAME_COUNT : parentInternalState.virtualNameCount;
      assert reservationState != null;
      isUsed = newName -> !reservationState.isAvailable(newName);
    }

    @Override
    public int getDictionaryIndex() {
      return dictionaryIndex;
    }

    @Override
    public int incrementDictionaryIndex() {
      return dictionaryIndex++;
    }

    private boolean checkParentPublicNameCountIsLessThanOrEqual() {
      int maxParentCount = 0;
      InternalNewNameState tmp = parentInternalState;
      while (tmp != null) {
        maxParentCount = Math.max(tmp.virtualNameCount, maxParentCount);
        tmp = tmp.parentInternalState;
      }
      assert maxParentCount <= virtualNameCount;
      return true;
    }

    @Override
    public int incrementNameIndex(boolean isDirectMethodCall) {
      assert checkParentPublicNameCountIsLessThanOrEqual();
      if (isDirectMethodCall) {
        return virtualNameCount + directNameCount++;
      } else {
        assert directNameCount == 0;
        return virtualNameCount++;
      }
    }

    private DexString getNewNameFor(DexMethod source) {
      DexString next = strategy.next(source, this, isUsed);
      assert reservationState.isAvailable(next);
      return next;
    }

    void printInternalState(
        MethodNamingState<?> expectedNamingState,
        Function<MethodNamingState<?>, DexType> stateKeyGetter,
        String indentation,
        PrintStream out) {
      assert expectedNamingState == MethodNamingState.this;

      DexType stateKey = stateKeyGetter.apply(expectedNamingState);
      out.print(indentation);
      out.print("InternalState(node=`");
      out.print(stateKey != null ? stateKey.toSourceString() : "<GLOBAL>");
      out.println("`)");

      printLastName(indentation + "  ", out);
      reservationState.printReservedNames(indentation + "  ", out);
      reservationState.printRenamings(indentation + "  ", out);

      if (parentInternalState != null) {
        parentInternalState.printInternalState(
            expectedNamingState.parent, stateKeyGetter, indentation + "  ", out);
      }
    }

    void printLastName(String indentation, PrintStream out) {
      out.print(indentation);
      out.print("public name count: ");
      out.print(virtualNameCount);
      out.print(", ");
      out.print("direct name count: ");
      out.println(directNameCount);
    }
  }
}
