/*
 * Copyright (c) 2015 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 */
package org.eclipse.scout.sdk.core.model.ecj;

import static java.util.Collections.emptyList;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Javadoc;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.scout.sdk.core.model.api.ISourceRange;
import org.eclipse.scout.sdk.core.model.api.IType;
import org.eclipse.scout.sdk.core.model.api.internal.TypeImplementor;
import org.eclipse.scout.sdk.core.model.spi.CompilationUnitSpi;
import org.eclipse.scout.sdk.core.model.spi.FieldSpi;
import org.eclipse.scout.sdk.core.model.spi.JavaElementSpi;
import org.eclipse.scout.sdk.core.model.spi.MethodSpi;
import org.eclipse.scout.sdk.core.model.spi.PackageSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeParameterSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeSpi;
import org.eclipse.scout.sdk.core.util.Ensure;
import org.eclipse.scout.sdk.core.util.FinalValue;
import org.eclipse.scout.sdk.core.util.JavaTypes;

public class DeclarationTypeWithEcj extends AbstractTypeWithEcj {
  private final CompilationUnitSpi m_cu;
  private final DeclarationTypeWithEcj m_declaringType;
  private final TypeDeclaration m_astNode;
  private final List<TypeSpi> m_typeArguments;

  private final FinalValue<PackageSpi> m_package;
  private final FinalValue<String> m_fqn;
  private final FinalValue<String> m_elementName;
  private final FinalValue<TypeSpi> m_superType;
  private final FinalValue<List<TypeSpi>> m_memberTypes;
  private final FinalValue<List<TypeSpi>> m_superInterfaces;
  private final FinalValue<List<TypeParameterSpi>> m_typeParameters;
  private final FinalValue<List<DeclarationAnnotationWithEcj>> m_annotations;
  private final FinalValue<List<MethodSpi>> m_methods;
  private final FinalValue<List<FieldSpi>> m_fields;
  private final FinalValue<ISourceRange> m_source;
  private final FinalValue<ISourceRange> m_javaDocSource;
  private final FinalValue<ISourceRange> m_staticInitSource;
  private int m_flags;

  protected DeclarationTypeWithEcj(JavaEnvironmentWithEcj env, CompilationUnitSpi cu, DeclarationTypeWithEcj declaringType, TypeDeclaration astNode) {
    super(env);
    m_cu = Ensure.notNull(cu);
    m_declaringType = declaringType;
    m_astNode = Ensure.notNull(astNode);
    m_typeArguments = emptyList(); // no arguments for declarations
    m_flags = -1; // mark as uninitialized
    m_package = new FinalValue<>();
    m_fqn = new FinalValue<>();
    m_elementName = new FinalValue<>();
    m_superType = new FinalValue<>();
    m_memberTypes = new FinalValue<>();
    m_superInterfaces = new FinalValue<>();
    m_typeParameters = new FinalValue<>();
    m_annotations = new FinalValue<>();
    m_methods = new FinalValue<>();
    m_fields = new FinalValue<>();
    m_source = new FinalValue<>();
    m_javaDocSource = new FinalValue<>();
    m_staticInitSource = new FinalValue<>();
  }

  @Override
  public JavaElementSpi internalFindNewElement() {
    TypeSpi newSpi = getJavaEnvironment().findType(getName());
    if (newSpi == null) {
      return null;
    }
    for (TypeSpi declType : newSpi.getCompilationUnit().getTypes()) {
      if (declType.getName().equals(getName())) {
        return declType;
      }
    }
    return null;
  }

  @Override
  public TypeBinding getInternalBinding() {
    return null;
  }

  @Override
  protected IType internalCreateApi() {
    return new TypeImplementor(this);
  }

  public TypeDeclaration getInternalTypeDeclaration() {
    return m_astNode;
  }

  @Override
  public int getArrayDimension() {
    return 0;
  }

  @Override
  public TypeSpi getLeafComponentType() {
    return null;
  }

  @Override
  public boolean isPrimitive() {
    return false;
  }

  @Override
  public boolean isAnonymous() {
    return m_astNode.name == null || m_astNode.name.length < 1;
  }

  @Override
  public String getName() {
    return m_fqn.computeIfAbsentAndGet(() -> {
      StringBuilder sb = new StringBuilder(128);

      char[] qualifiedPackageName = m_astNode.binding.qualifiedPackageName();
      if (qualifiedPackageName != null && qualifiedPackageName.length > 0) {
        sb.append(qualifiedPackageName);
        sb.append(JavaTypes.C_DOT);
      }

      // collect declaring types
      Deque<char[]> namesBottomUp = new ArrayDeque<>();
      TypeDeclaration declaringType = m_astNode;
      while (declaringType != null) {
        namesBottomUp.add(declaringType.name);
        declaringType = declaringType.enclosingType;
      }

      Iterator<char[]> namesTopDown = namesBottomUp.descendingIterator();
      sb.append(namesTopDown.next()); // there must be at least one type name
      while (namesTopDown.hasNext()) {
        sb.append(JavaTypes.C_DOLLAR).append(namesTopDown.next());
      }
      return sb.toString();
    });
  }

  @Override
  public String getElementName() {
    return m_elementName.computeIfAbsentAndGet(() -> new String(m_astNode.name));
  }

  @Override
  public PackageSpi getPackage() {
    return m_package.computeIfAbsentAndGet(() -> {
      char[] qualifiedPackageName = m_astNode.binding.qualifiedPackageName();
      if (qualifiedPackageName != null && qualifiedPackageName.length > 0) {
        return javaEnvWithEcj().createPackage(new String(qualifiedPackageName));
      }
      return javaEnvWithEcj().createDefaultPackage();
    });
  }

  @Override
  public List<DeclarationAnnotationWithEcj> getAnnotations() {
    return m_annotations.computeIfAbsentAndGet(() -> SpiWithEcjUtils.createDeclarationAnnotations(javaEnvWithEcj(), this, m_astNode.annotations));
  }

  @Override
  public List<FieldSpi> getFields() {
    return m_fields.computeIfAbsentAndGet(() -> {
      FieldDeclaration[] fields = m_astNode.fields;
      if (fields == null || fields.length < 1) {
        return emptyList();
      }

      List<FieldSpi> result = new ArrayList<>(fields.length);
      for (FieldDeclaration fd : fields) {
        result.add(javaEnvWithEcj().createDeclarationField(this, fd));
      }
      return result;
    });
  }

  @Override
  public List<MethodSpi> getMethods() {
    return m_methods.computeIfAbsentAndGet(() -> {
      AbstractMethodDeclaration[] methods = m_astNode.methods;
      if (methods == null || methods.length < 1) {
        return emptyList();
      }

      List<MethodSpi> result = new ArrayList<>(methods.length);
      char[] constrName = "<init>".toCharArray();
      for (AbstractMethodDeclaration a : methods) {
        if (a.bodyStart <= 0) { // skip compiler generated methods
          continue;
        }
        if (Arrays.equals(constrName, a.selector)) {
          continue;
        }
        result.add(javaEnvWithEcj().createDeclarationMethod(this, a));
      }
      return result;
    });
  }

  @Override
  public List<TypeSpi> getTypes() {
    return m_memberTypes.computeIfAbsentAndGet(() -> {
      TypeDeclaration[] memberTypes = m_astNode.memberTypes;
      if (memberTypes == null || memberTypes.length < 1) {
        return emptyList();
      }
      List<TypeSpi> result = new ArrayList<>(memberTypes.length);
      for (TypeDeclaration d : memberTypes) {
        result.add(new DeclarationTypeWithEcj(javaEnvWithEcj(), m_cu, this, d));
      }
      return result;
    });
  }

  @Override
  public TypeSpi getSuperClass() {
    return m_superType.computeIfAbsentAndGet(() -> {
      if (m_astNode.superclass == null) {
        return null;
      }
      TypeBinding tb = m_astNode.superclass.resolvedType;
      if (tb == null) {
        return null;
      }
      return SpiWithEcjUtils.bindingToType(javaEnvWithEcj(), tb);
    });
  }

  @Override
  public List<TypeSpi> getSuperInterfaces() {
    return m_superInterfaces.computeIfAbsentAndGet(() -> {
      TypeReference[] refs = m_astNode.superInterfaces;
      if (refs == null || refs.length < 1) {
        return emptyList();
      }
      List<TypeSpi> result = new ArrayList<>(refs.length);
      for (TypeReference r : refs) {
        TypeBinding b = r.resolvedType;
        if (b != null) {
          TypeSpi t = SpiWithEcjUtils.bindingToType(javaEnvWithEcj(), b);
          if (t != null) {
            result.add(t);
          }
        }
      }
      return result;
    });
  }

  @Override
  public int getFlags() {
    if (m_flags < 0) {
      m_flags = SpiWithEcjUtils.getTypeFlags(m_astNode.modifiers, m_astNode.allocation, SpiWithEcjUtils.hasDeprecatedAnnotation(m_astNode.annotations));
    }
    return m_flags;
  }

  @Override
  public List<TypeSpi> getTypeArguments() {
    return m_typeArguments;
  }

  @Override
  public List<TypeParameterSpi> getTypeParameters() {
    return m_typeParameters.computeIfAbsentAndGet(() -> SpiWithEcjUtils.toTypeParameterSpi(m_astNode.typeParameters, this, javaEnvWithEcj()));
  }

  @Override
  public boolean hasTypeParameters() {
    TypeParameter[] typeParams = m_astNode.typeParameters;
    return typeParams != null && typeParams.length > 0;
  }

  @Override
  public CompilationUnitSpi getCompilationUnit() {
    return m_cu;
  }

  @Override
  public TypeSpi getDeclaringType() {
    return m_declaringType;
  }

  @Override
  public ISourceRange getSource() {
    return m_source.computeIfAbsentAndGet(() -> javaEnvWithEcj().getSource(m_cu, m_astNode.declarationSourceStart, m_astNode.declarationSourceEnd));
  }

  @Override
  public ISourceRange getSourceOfStaticInitializer() {
    return m_staticInitSource.computeIfAbsentAndGet(() -> {
      FieldDeclaration[] fields = m_astNode.fields;
      if (fields != null) {
        for (FieldDeclaration fieldDecl : fields) {
          if (fieldDecl.type == null && fieldDecl.name == null) {
            return javaEnvWithEcj().getSource(m_cu, fieldDecl.declarationSourceStart, fieldDecl.declarationSourceEnd);
          }
        }
      }
      return null;
    });
  }

  @Override
  public ISourceRange getJavaDoc() {
    return m_javaDocSource.computeIfAbsentAndGet(() -> {
      Javadoc doc = m_astNode.javadoc;
      if (doc != null) {
        return javaEnvWithEcj().getSource(m_cu, doc.sourceStart, doc.sourceEnd);
      }
      return null;
    });
  }

  @Override
  public boolean isWildcardType() {
    return false;
  }
}
