/*
 * Copyright 2014 Objectos, Fábrica de Software LTDA.
 *
 * 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 br.com.objectos.way.code;

import br.com.objectos.way.testable.Equality;
import br.com.objectos.way.testable.Testable;
import br.com.objectos.way.testable.Tester;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * @author marcio.endo@objectos.com.br (Marcio Endo)
 */
public class ClassInfo implements Testable {

  private static final Tester<ClassInfo> TESTER = Tester.of(ClassInfo.class)
      .add("typeInfo", o -> o.typeInfo)
      .build();

  public final TypeInfo typeInfo;

  ClassInfo(TypeInfo typeInfo) {
    this.typeInfo = typeInfo;
  }

  public Optional<InterfaceInfo> getInterface(Class<?> type) {
    return typeInfo.getInterface(type);
  }

  @Override
  public Equality isEqualTo(Object that) {
    return TESTER.test(this, that);
  }

  public JavaFile toJavaFile(TypeSpec typeSpec) {
    return typeInfo.toJavaFile(typeSpec);
  }

  public String toSimpleNameSuffix(String suffix) {
    return typeInfo.toSimpleNameSuffix(suffix);
  }

  public SimpleTypeInfo toSimpleTypeInfo() {
    return typeInfo.toSimpleTypeInfo();
  }

  public AccessInfo accessInfo() {
    return typeInfo.accessInfo();
  }

  public ClassName className() {
    return typeInfo.className();
  }

  public ClassName classNameSuffix(String suffix) {
    return typeInfo.classNameSuffix(suffix);
  }

  public Stream<ConstructorInfo> constructorInfoStream() {
    return typeInfo.constructorInfoList().stream();
  }

  public Stream<FieldInfo> fieldInfoStream() {
    return typeInfo.fieldInfoList().stream();
  }

  public Stream<MethodInfo> methodInfoStream() {
    return typeInfo.methodInfoStream();
  }

  public String qualifiedName() {
    return typeInfo.qualifiedName();
  }

  public String simpleName() {
    return typeInfo.simpleName();
  }

  public TypeName typeName() {
    return typeInfo.typeName();
  }

  public TypeName typeNameRaw() {
    return typeInfo.typeNameRaw();
  }

  public TypeName typeNameUnbounded() {
    return typeInfo.typeNameUnbounded();
  }

  public TypeParameterInfoMap typeParameterInfoMap() {
    return typeInfo.typeParameterInfoMap();
  }

  public String varName() {
    return typeInfo.varName();
  }

  @Override
  public final int hashCode() {
    return typeInfo.hashCode();
  }

  @Override
  public final boolean equals(final Object obj) {
    if (obj == this) {
      return true;
    }
    if (obj instanceof ClassInfo) {
      final ClassInfo that = (ClassInfo) obj;
      return Objects.equals(typeInfo, that.typeInfo);
    } else {
      return false;
    }
  }

}