package meta;

import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import encapsulation.RPNCalc;
import objectstructures.Person;

public class ClassDiagram {

  private Class<?> cls;

  ClassDiagram(Class<?> cls) {
    this.cls = cls;
  }

  private char detectModifiers(Member m) {
    String firstModifier = 
      Modifier
        .toString(m.getModifiers())
        .split("\\s")[0];

    return firstModifier == "public" ? '+' : '-';
  }

  private String formatFields() {
    return
      Stream.of(this.cls.getDeclaredFields())
        .map(f -> detectModifiers(f) + f.getName() + ": " + f.getType().getSimpleName())
        .collect(Collectors.joining("\n  "));
  }

  private String formatParameters(Method m) {
    return
      Stream.of(m.getParameters())
        .map(p -> p.getType().getSimpleName() + " " + p.getName())
        .collect(Collectors.joining(", "));
  }

  private String formatMethods() {
    return
      Stream.of(this.cls.getDeclaredMethods())
        .map(m -> 
          String.format(
            "%c%s(%s): %s"
            , detectModifiers(m)
            , m.getName()
            , formatParameters(m)
            , m.getReturnType().getSimpleName()
          ))
        .collect(Collectors.joining("\n  "));
  }

  @Override
  public String toString() {
    return String.format(
      """

      class %s {
        %s
        %s
      }

      """
      , this.cls.getName()
      , this.formatFields()
      , this.formatMethods()
    );
  }

  public static void main(String[] args) {
    ClassDiagram cd = new ClassDiagram(Person.class);
    System.out.println(cd);
  }
}
