package org.eclipse.scout.nls.sdk.services.model.ws.project;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.scout.nls.sdk.extension.INlsProjectProvider;
import org.eclipse.scout.nls.sdk.internal.NlsCore;
import org.eclipse.scout.nls.sdk.internal.jdt.NlsJdtUtility;
import org.eclipse.scout.nls.sdk.model.workspace.project.INlsProject;
import org.eclipse.scout.nls.sdk.services.model.ws.NlsServiceType;
import org.eclipse.scout.sdk.RuntimeClasses;
import org.eclipse.scout.sdk.ScoutSdkCore;
import org.eclipse.scout.sdk.internal.workspace.IScoutBundleConstantes;
import org.eclipse.scout.sdk.util.jdt.JdtUtility;
import org.eclipse.scout.sdk.util.log.ScoutStatus;
import org.eclipse.scout.sdk.util.type.TypeUtility;
import org.eclipse.scout.sdk.util.typecache.TypeCacheAccessor;
import org.eclipse.scout.sdk.workspace.IScoutBundle;
import org.eclipse.scout.sdk.workspace.IScoutProject;

@SuppressWarnings("restriction")
public class ServiceNlsProjectProvider implements INlsProjectProvider {

  public ServiceNlsProjectProvider() {
  }

  /**
   * @return All text provider services in the workspace.
   * @throws JavaModelException
   */
  public static IType[] getRegisteredTextProviderTypes() throws JavaModelException {
    return getRegisteredTextProviderTypes(null, null);
  }

  /**
   * Gets the registered (in plugin.xml) text provider service types ordered by priority.
   *
   * @param returnDocServices
   *          If true, only Docs text provider services (implementing marker interface
   *          <code>IDocumentationTextProviderService</code>) are returned. Otherwise only non-docs text provider
   *          services are
   *          returned. If the parameter is null, all text services are returned.
   * @param projectFilter
   *          List of project names. Only services that belong to these projects are returned. if null is passed, all
   *          services are returned.
   * @return
   * @throws JavaModelException
   */
  private static IType[] getRegisteredTextProviderTypes(Boolean returnDocServices, String[] projectFilter) throws JavaModelException {

    class TextProviderService {
      private final IType textProvider;
      private final IJavaProject project;

      private TextProviderService(IType t) {
        textProvider = t;
        project = t.getJavaProject();
      }

      @Override
      public int hashCode() {
        int ret = 1;
        ret = ret * 27 + textProvider.getFullyQualifiedName().hashCode();
        ret = ret * 19 + project.getElementName().hashCode();
        return ret;
      }

      @Override
      public boolean equals(Object obj) {
        if (obj instanceof TextProviderService) {
          TextProviderService o = (TextProviderService) obj;
          return textProvider.getFullyQualifiedName().equals(o.textProvider.getFullyQualifiedName()) &&
              project.getElementName().equals(o.project.getElementName());
        }
        else {
          return false;
        }
      }
    }

    class TextProviderServiceDeclaration {
      private final TextProviderService svc;
      private final float prio;

      private TextProviderServiceDeclaration(TextProviderService s, float p) {
        svc = s;
        prio = p;
      }
    }

    IType superType = TypeUtility.getType(RuntimeClasses.AbstractDynamicNlsTextProviderService);
    if (superType == null) return null;

    IType[] serviceImpls = TypeCacheAccessor.getHierarchyCache().getPrimaryTypeHierarchy(superType).getAllSubtypes(superType);
    HashMap<TextProviderService, TextProviderServiceDeclaration> result = new HashMap<TextProviderService, TextProviderServiceDeclaration>(serviceImpls.length);
    IExtension[] allServiceExtensions = PDECore.getDefault().getExtensionsRegistry().findExtensions(IScoutBundleConstantes.EXTENSION_POINT_SERVICES, true);
    for (IExtension e : allServiceExtensions) {
      for (IConfigurationElement c : e.getConfigurationElements()) {
        for (IType serviceType : serviceImpls) {
          if (acceptsFilter(returnDocServices, projectFilter, serviceType)) {
            if (IScoutBundleConstantes.EXTENSION_ELEMENT_SERVICE.equals(c.getName())) {
              String serviceClassDef = c.getAttribute("class");
              if (serviceClassDef != null && serviceClassDef.equals(serviceType.getFullyQualifiedName())) {
                TextProviderService s = new TextProviderService(serviceType);
                TextProviderServiceDeclaration d = new TextProviderServiceDeclaration(s, getPriority(serviceType, c));

                // if the same service is registered more than once with different priorities: use always the one with the higher priority
                // meaning: if we have the current service with a higher prio in the list already -> do not overwrite with the new one.
                TextProviderServiceDeclaration existing = result.get(s);
                if (existing == null || existing.prio < d.prio) {
                  // we do not have this service or we have a service with lower prio -> overwrite
                  result.put(s, d);
                }
              }
            }
          }
        }
      }
    }

    // we have ensured that every service is registered with its highest prio -> sort all services by prio
    TextProviderServiceDeclaration[] sortedArrayHighestPrioFirst = result.values().toArray(new TextProviderServiceDeclaration[result.size()]);
    Arrays.sort(sortedArrayHighestPrioFirst, new Comparator<TextProviderServiceDeclaration>() {
      @Override
      public int compare(TextProviderServiceDeclaration o1, TextProviderServiceDeclaration o2) {
        return new Float(o2.prio).compareTo(new Float(o1.prio));
      }
    });

    // return the types of the services ordered by priority
    IType[] returnValueSorted = new IType[sortedArrayHighestPrioFirst.length];
    for (int i = 0; i < returnValueSorted.length; i++) {
      returnValueSorted[i] = sortedArrayHighestPrioFirst[i].svc.textProvider;
    }
    return returnValueSorted;
  }

  private static boolean acceptsFilter(Boolean returnDocServices, String[] projects, IType candidate) throws JavaModelException {
    boolean acceptsDocPart = returnDocServices == null || returnDocServices == isDocsService(candidate);
    if (acceptsDocPart) {
      if (candidate.isReadOnly()) return true; // always include all text services from the platform
      if (projects == null) return true; // no project filter and doc filter is valid -> filter matches

      // check project filter
      for (String p : projects) {
        if (candidate.getJavaProject().getProject().getName().equals(p)) return true;
      }
    }
    return false;
  }

  private static boolean isDocsService(IType service) throws JavaModelException {
    String docsInterfaceClassName = RuntimeClasses.IDocumentationTextProviderService.substring(RuntimeClasses.IDocumentationTextProviderService.lastIndexOf('.') + 1);
    for (String ifs : service.getSuperInterfaceNames()) {
      if (docsInterfaceClassName.equals(ifs)) {
        return true;
      }
    }
    return false;
  }

  private static float getPriority(IType registration, IConfigurationElement config) {
    // first check plugin.xml definition for ranking
    String xmlRank = config.getAttribute(IScoutBundleConstantes.EXTENSION_SERVICE_RANKING);
    if (xmlRank != null && xmlRank.length() > 0) {
      try {
        return Float.parseFloat(xmlRank);
      }
      catch (NumberFormatException e) {
        //nop
      }
    }

    // second check class annotation
    try {
    	IAnnotation a = JdtUtility.getAnnotation(registration, RuntimeClasses.Ranking);
        Double val = JdtUtility.getNumericAnnotationValue(a, "value");
        if (val != null) {
          return val.floatValue();
        }
    }
    catch (Exception e) {
      //nop
    }

    // if nothing defined: default ranking = 0
    return 0.0f;
  }

  private ServiceNlsProject getServiceNlsProject(IType serviceType) {
    if (!TypeUtility.exists(serviceType)) {
      NlsCore.logError("nls service type '" + serviceType.getFullyQualifiedName() + "' does not exist");
      return null;
    }

    NlsServiceType type = new NlsServiceType(serviceType);
    if (type.getTranslationsFolderName() == null) {
      NlsCore.logWarning("The NLS Service for Type '" + serviceType.getFullyQualifiedName() + "' could not be parsed. Ensure that the method '"
          + NlsServiceType.DYNAMIC_NLS_BASE_NAME_GETTER + "' is available and returns a String literal like \"resources.texts.Texts\" directly.");
      return null;
    }

    return new ServiceNlsProject(type);
  }

  private INlsProject getNlsProjectTree(boolean returnDocServices, String[] projectFilter) throws CoreException {
    return getNlsProjectTree(getRegisteredTextProviderTypes(returnDocServices, projectFilter));
  }

  private INlsProject getNlsProjectTree(IType[] textProviderServices) throws CoreException {
    ServiceNlsProject previous = null;
    ServiceNlsProject root = null;
    for (IType type : textProviderServices) {
      ServiceNlsProject p = getServiceNlsProject(type);
      if (p != null) {
        // remember the first project (the one with the highest prio)
        if (root == null) {
          root = p;
        }

        // set the current as parent of the previous instance -> build up tree
        if (previous != null) {
          previous.setParent(p);
        }

        // remember the previous provider for the next iteration
        previous = p;
      }
      else if (root == null) {
        // first Type in the chain could not be parsed.
        // this is also the Type that e.g. the editor would show -> show error
        //NlsCore.logError("The NLS Service for Type " + type.getFullyQualifiedName() + " could not be parsed.");
        throw new CoreException(new ScoutStatus("The NLS Service for Type " + type.getFullyQualifiedName() + " could not be parsed."));
      }
    }
    return root;
  }

  private static String[] getProjectNames(IScoutBundle[] scoutBundles) {
    if (scoutBundles == null || scoutBundles.length < 1) return null;

    String[] ret = new String[scoutBundles.length];
    for (int i = 0; i < scoutBundles.length; i++) {
      ret[i] = scoutBundles[i].getBundleName();
    }
    return ret;
  }

  private static void addBundlesRec(IScoutProject p, HashSet<IScoutBundle> collector) {
    for (IScoutBundle b : p.getAllScoutBundles()) {
      collector.add(b);
    }
    for (IScoutProject subP : p.getSubProjects()) {
      addBundlesRec(subP, collector);
    }
  }

  private static IScoutBundle[] getScoutBundlesForType(IType type) {
    IScoutBundle b = ScoutSdkCore.getScoutWorkspace().getScoutBundle(type.getJavaProject().getProject());
    if (b != null) {
      IScoutProject root = b.getScoutProject();
      return getScoutBundlesForProject(root);
    }
    else {
      return null;
    }
  }

  private static IScoutBundle[] getScoutBundlesForProject(IScoutProject p) {
    if (p == null) return null;
    HashSet<IScoutBundle> collector = new HashSet<IScoutBundle>();

    // find root scout project of the given project (may be a sub project).
    IScoutProject root = p;
    while (root.getParentProject() != null) {
      root = root.getParentProject();
    }

    // collect all bundles that belong to the root project that belongs to the project p.
    // assume that all these bundles together build the application so all text services of these projects should be available.
    addBundlesRec(root, collector);
    return collector.toArray(new IScoutBundle[collector.size()]);
  }

  private INlsProject getNlsProjectTree(IType type) throws CoreException {
    IType[] nlsProviders = getRegisteredTextProviderTypes(isDocsService(type), getProjectNames(getScoutBundlesForType(type)));
    if (nlsProviders == null) return null;

    String searchString = getTypeIdentifyer(type);
    ArrayList<IType> filtered = new ArrayList<IType>(nlsProviders.length);
    boolean minFound = false;
    for (IType t : nlsProviders) {
      if (getTypeIdentifyer(t).equals(searchString) && !minFound) {
        minFound = true;
      }

      if (minFound) {
        filtered.add(t);
      }
    }

    return getNlsProjectTree(filtered.toArray(new IType[filtered.size()]));
  }

  private static String getTypeIdentifyer(IType t) {
    return t.getJavaProject().getProject().getName() + "/" + t.getFullyQualifiedName();
  }

  @Override
  public INlsProject getProject(Object[] args) {
    if (args != null) {
      if (args.length == 1) {
        if (args[0] instanceof IType) {
          // text service type
          return getProjectByTextServiceType((IType) args[0]);
        }
        else if (args[0] instanceof IFile) {
          // text service file
          return getProjectByTextServiceFile((IFile) args[0]);
        }
      }
      else if (args.length == 2 && args[0] instanceof IType) {
        IType t1 = (IType) args[0];
        boolean returnDocServices = !(RuntimeClasses.TEXTS.equals(t1.getFullyQualifiedName()));

        if (args[1] instanceof IScoutProject || args[1] == null) {
          // all text services in the given project with given kind (texts or normal)
          return getAllProjects(returnDocServices, getScoutBundlesForProject((IScoutProject) args[1]));
        }
        else if (args[1] instanceof IType) {
          // all text services with given kind available in the plugins defining the given type
          return getAllProjects(returnDocServices, getScoutBundlesForType((IType) args[1]));
        }
      }
    }
    return null;
  }

  private INlsProject getAllProjects(boolean returnDocServices, IScoutBundle[] wsBundles) {
    try {
      return getNlsProjectTree(returnDocServices, getProjectNames(wsBundles));
    }
    catch (CoreException e) {
      NlsCore.logWarning("Could not load full text provider service tree.", e);
      return null;
    }
  }

  private INlsProject getProjectByTextServiceFile(IFile f) {
    try {
      IType type = NlsJdtUtility.getITypeForFile(f);
      if (type != null) {
        return NlsCore.getNlsWorkspace().getNlsProject(new Object[]{type});
      }
    }
    catch (CoreException e) {
      NlsCore.logWarning("Could not load text provider services for file: " + f.getFullPath().toString(), e);
    }
    return null;
  }

  private INlsProject getProjectByTextServiceType(IType textservice) {
    try {
      return getNlsProjectTree(textservice);
    }
    catch (CoreException e) {
      NlsCore.logWarning("Could not load text provider services for " + textservice.getFullyQualifiedName(), e);
      return null;
    }
  }
}
