// Copyright (c) 2018, 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.kotlin;

import com.android.tools.r8.naming.MemberNaming;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Represents the definition of a Kotlin class.
 *
 * <p>See https://kotlinlang.org/docs/reference/classes.html</p>
 */
class TestKotlinClass {

  /**
   * This is the suffix appended by Kotlin compiler to getter and setter method names of
   * internal properties.
   *
   * It must match the string passed in command-line option "-module-name" of Kotlin compiler. The
   * default value is "main".
   */
  private static final String KOTLIN_MODULE_NAME = "main";

  enum Visibility {
    PUBLIC,
    INTERNAL,
    PROTECTED,
    PRIVATE;
  }

  enum AccessorKind {
    FROM_COMPANION("cp"),
    FROM_INNER("p"),
    FROM_LAMBDA("lp");

    private final String accessorSuffix;

    AccessorKind(String accessorSuffix) {
      this.accessorSuffix = accessorSuffix;
    }

    public String getAccessorSuffix() {
      return accessorSuffix;
    }
  }

  protected static class KotlinProperty {
    private final String name;
    private final String type;
    private final Visibility visibility;
    private final int index;

    private KotlinProperty(String name, String type, Visibility visibility, int index) {
      this.name = name;
      this.type = type;
      this.index = index;
      this.visibility = visibility;
    }

    public String getName() {
      return name;
    }

    public String getType() {
      return type;
    }

    public Visibility getVisibility() {
      return visibility;
    }

    public int getIndex() {
      return index;
    }
  }

  protected final String className;
  protected final Map<String, KotlinProperty> properties = Maps.newHashMap();

  public TestKotlinClass(String className) {
    this.className = className;
  }

  public String getClassName() {
    return className;
  }

  public TestKotlinClass addProperty(String name, String type, Visibility visibility) {
    assert !properties.containsKey(name);
    properties.put(name, new KotlinProperty(name, type, visibility, properties.size()));
    return this;
  }

  protected KotlinProperty getProperty(String name) {
    assert properties.containsKey(name);
    return properties.get(name);
  }

  public MemberNaming.MethodSignature getGetterForProperty(String propertyName) {
    KotlinProperty property = getProperty(propertyName);
    String type = property.type;
    String getterName = computeGetterName(propertyName);
    if (property.getVisibility() == Visibility.INTERNAL) {
      getterName = appendInternalSuffix(getterName);
    }
    return new MemberNaming.MethodSignature(getterName, type, Collections.emptyList());
  }

  public MemberNaming.MethodSignature getSetterForProperty(String propertyName) {
    KotlinProperty property = getProperty(propertyName);
    String setterName = computeSetterName(propertyName);
    if (property.getVisibility() == Visibility.INTERNAL) {
      setterName = appendInternalSuffix(setterName);
    }
    return new MemberNaming.MethodSignature(setterName, "void",
        Collections.singleton(property.getType()));
  }

  public MemberNaming.MethodSignature getGetterAccessorForProperty(String propertyName,
      AccessorKind accessorKind) {
    KotlinProperty property = getProperty(propertyName);
    String getterName = computeGetterName(propertyName);
    // Unlike normal getter, module name is not appended for accessor method of internal property.
    getterName = wrapWithAccessorPrefixAndSuffix(accessorKind, getterName);
    List<String> argumentTypes;
    if (accessorKind != AccessorKind.FROM_COMPANION) {
      argumentTypes = ImmutableList.of(getClassName());
    } else {
      argumentTypes = ImmutableList.of();
    }
    return new MemberNaming.MethodSignature(getterName, property.type, argumentTypes);
  }

  public MemberNaming.MethodSignature getSetterAccessorForProperty(String propertyName,
      AccessorKind accessorKind) {
    KotlinProperty property = getProperty(propertyName);
    String setterName = computeSetterName(propertyName);
    // Unlike normal setter, module name is not appended for accessor method of internal property.
    setterName = wrapWithAccessorPrefixAndSuffix(accessorKind, setterName);
    List<String> argumentTypes;
    if (accessorKind != AccessorKind.FROM_COMPANION) {
      argumentTypes = ImmutableList.of(getClassName(), property.getType());
    } else {
      argumentTypes = ImmutableList.of(property.getType());
    }
    return new MemberNaming.MethodSignature(setterName, "void", argumentTypes);
  }

  private static String computeGetterName(String propertyName) {
    if (propertyName.length() > 2 && propertyName.startsWith("is")
        && (propertyName.charAt(2) == '_' || Character.isUpperCase(propertyName.charAt(2)))) {
      // Getter for property "isAbc" is "isAbc".
      return propertyName;
    } else {
      // Getter for property "abc" is "getAbc".
      return "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
    }
  }

  private static String computeSetterName(String propertyName) {
    return "set" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
  }

  private static String appendInternalSuffix(String name) {
    return name + "$" + KOTLIN_MODULE_NAME;
  }

  private String wrapWithAccessorPrefixAndSuffix(AccessorKind accessorKind, String methodName) {
    return "access$" + methodName + "$" + accessorKind.getAccessorSuffix();
  }

}
