// 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>
 */
public 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);
    return getGetterForProperty(property, property.getVisibility() == Visibility.INTERNAL);
  }

  public MemberNaming.MethodSignature getSetterForProperty(String propertyName) {
    KotlinProperty property = getProperty(propertyName);
    return getSetterForProperty(property, property.getVisibility() == Visibility.INTERNAL);
  }

  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);
  }

  protected final MemberNaming.MethodSignature getGetterForProperty(KotlinProperty property,
      boolean applyMangling) {
    String type = property.type;
    String getterName = computeGetterName(property.name);
    if (applyMangling) {
      getterName = appendInternalSuffix(getterName);
    }
    return new MemberNaming.MethodSignature(getterName, type, Collections.emptyList());
  }

  protected final MemberNaming.MethodSignature getSetterForProperty(KotlinProperty property,
      boolean applyMangling) {
    String setterName = computeSetterName(property.name);
    if (applyMangling) {
      setterName = appendInternalSuffix(setterName);
    }
    return new MemberNaming.MethodSignature(setterName, "void",
        Collections.singleton(property.getType()));
  }

  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();
  }

}
