/*******************************************************************************
 * Copyright (c) 2008-2010 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *      Sonatype, Inc. - initial API and implementation
 *******************************************************************************/

package org.eclipse.m2e.editor.xml;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.text.templates.TemplateProposal;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer;

import org.apache.maven.project.MavenProject;

import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.editor.pom.PomTemplate;
import org.eclipse.m2e.editor.pom.PomTemplateContext;
import org.eclipse.m2e.editor.pom.XmlUtils;
import org.eclipse.m2e.editor.xml.internal.Messages;


/**
 * @author Lukas Krecan
 * @author Eugene Kuleshov
 */
@SuppressWarnings("restriction")
public class PomContentAssistProcessor extends DefaultXMLCompletionProposalComputer {

  private static Set<PomTemplateContext> expressionproposalContexts = EnumSet.of( //
      PomTemplateContext.GROUP_ID, PomTemplateContext.ARTIFACT_ID, //
      //version is intentionally not included as we have specialized handling there..
      //PomTemplateContext.VERSION,
      PomTemplateContext.PACKAGING, PomTemplateContext.TYPE, //
      PomTemplateContext.CLASSIFIER, PomTemplateContext.SCOPE, PomTemplateContext.SYSTEM_PATH, //
      PomTemplateContext.PROPERTIES, PomTemplateContext.MODULE, //
      PomTemplateContext.PHASE, PomTemplateContext.GOAL, PomTemplateContext.CONFIGURATION, //
      PomTemplateContext.SOURCEDIRECTORY, PomTemplateContext.SCRIPTSOURCEDIRECTORY,
      PomTemplateContext.TESTSOURCEDIRECTORY, //
      PomTemplateContext.OUTPUTDIRECTORY, PomTemplateContext.TESTOUTPUTDIRECTORY, //
      PomTemplateContext.DIRECTORY, PomTemplateContext.FILTER, //
      //this one is both important and troubling.. but having a context for everything is weird.
      PomTemplateContext.UNKNOWN);

  private static List<String> hardwiredProperties = Collections.unmodifiableList(Arrays.asList( //
      "basedir", "project.basedir", //
      "project.version", "project.groupId", "project.artifactId", "project.version", "project.name", //
      "project.build.directory", "project.build.outputDirectory"));

  protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition,
      CompletionProposalInvocationContext ctx) {
    PomTemplateContext context = PomTemplateContext.fromNode(contentAssistRequest.getParent());

    if(PomTemplateContext.CONFIGURATION == context) {
      addTemplateProposals(contentAssistRequest, context, ctx.getViewer(), true);
    }
  }

  protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition,
      CompletionProposalInvocationContext ctx) {
    PomTemplateContext context = PomTemplateContext.fromNode(contentAssistRequest.getParent());

    // wst content assist doesn't provide matchString in text content
    int offset = contentAssistRequest.getReplacementBeginPosition();
    String prefix = extractPrefix(ctx.getViewer(), offset);
    contentAssistRequest.setMatchString(prefix);
    contentAssistRequest.setReplacementBeginPosition(offset - prefix.length());
    contentAssistRequest.setReplacementLength(prefix.length());

    addExpressionProposals(contentAssistRequest, context, ctx.getViewer());
    addGenerateProposals(contentAssistRequest, context, ctx.getViewer());
    addTemplateProposals(contentAssistRequest, context, ctx.getViewer(), false);
  }

  /**
   * this is a proposal method for adding expressions when ${ is typed..
   * 
   * @param request
   * @param context
   * @param currentNode
   * @param prefixPath
   */
  private void addExpressionProposals(ContentAssistRequest request, PomTemplateContext context,
      ITextViewer sourceViewer) {
    String prefix = request.getMatchString();
    int exprStart = prefix.lastIndexOf("${"); //$NON-NLS-1$
    if(exprStart != -1) {
      //the regular prefix is separated by whitespace and <> brackets only, we need to cut the last portion
      String realExpressionPrefix = prefix.substring(exprStart);
      if(realExpressionPrefix.contains("}")) { //$NON-NLS-1$
        //the expression is not opened..
        return;
      }

      if(expressionproposalContexts.contains(context)) {
        //add all effective pom expressions
        MavenProject prj = XmlUtils.extractMavenProject(sourceViewer);
        Region region = new Region(request.getReplacementBeginPosition() + exprStart, realExpressionPrefix.length());
        Set<String> collect = new TreeSet<String>();

        String currentProp = null;
        Node node = request.getParent();
        if(PomTemplateContext.getAncestor(node, "properties", "project") != null
            || PomTemplateContext.getAncestor(node, "properties", "profile", "profiles", "project") != null) {
          currentProp = node.getLocalName();
        }

        if(prj != null) {
          Properties props = prj.getProperties();
          if(props != null) {
            for(Object key : props.keySet()) {
              String keyString = key.toString();
              if(keyString.equals(currentProp)) {
                // do not allow recursive property usage
                continue;
              }
              if(("${" + keyString).startsWith(realExpressionPrefix)) { //$NON-NLS-1$
                collect.add(keyString);
              }
            }
          }
        }

        //add a few hardwired values as well
        for(String prop : hardwiredProperties) {
          if(("${" + prop).startsWith(realExpressionPrefix)) { //$NON-NLS-1$
            collect.add(prop);
          }
        }
        for(String key : collect) {
          request.addProposal(new InsertExpressionProposal(region, key, prj));
        }
      }
    }
  }

  private void addGenerateProposals(ContentAssistRequest request, PomTemplateContext context,
      ITextViewer sourceViewer) {

    String prefix = request.getMatchString();
    if(prefix.trim().length() != 0) {
      //only provide these generate proposals when there is no prefix.
      return;
    }

    Node node = request.getParent();

    if(context == PomTemplateContext.PARENT && node.getNodeName().equals("parent")) { //$NON-NLS-1$
      Element parent = (Element) node;
      Element relPath = XmlUtils.findChild(parent, "relativePath"); //$NON-NLS-1$
      if(relPath == null) {
        //only show when no relpath already defined..
        String relative = findRelativePath(sourceViewer, parent);
        if(relative != null) {
          Region region = new Region(request.getReplacementBeginPosition(), 0);
          ICompletionProposal proposal = new CompletionProposal("<relativePath>" + relative + "</relativePath>", //$NON-NLS-1$ //$NON-NLS-2$
              region.getOffset(), region.getLength(), 0, //
              PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD), //
              NLS.bind(Messages.PomContentAssistProcessor_insert_relPath_title, relative), null, null);
          request.addProposal(proposal);
        }
      }
    }
    if(context == PomTemplateContext.RELATIVE_PATH) {
      //completion in the text portion of relative path
      Element parent = (Element) node.getParentNode();
      if(parent != null && "parent".equals(parent.getNodeName())) { //$NON-NLS-1$
        String relative = findRelativePath(sourceViewer, parent);
        String textContent = XmlUtils.getTextValue(node);
        if(relative != null && !relative.equals(textContent)) {
          Region region = new Region(request.getReplacementBeginPosition() - prefix.length(), prefix.length());
          if(request.getNode() instanceof IndexedRegion && request.getNode() instanceof Text) {
            //for <relativePath>|</relativePath> the current node is the element node and not the text node
            //only replace the text node content..
            IndexedRegion index = (IndexedRegion) request.getNode();
            region = new Region(index.getStartOffset(), index.getEndOffset() - index.getStartOffset());
          }
          ICompletionProposal proposal = new CompletionProposal(relative, region.getOffset(), region.getLength(), 0,
              PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD),
              NLS.bind(Messages.PomContentAssistProcessor_set_relPath_title, relative), null, null);
          request.addProposal(proposal);
        }
      }
    }
    if(context == PomTemplateContext.DEPENDENCIES || context == PomTemplateContext.PROFILE
        || context == PomTemplateContext.DEPENDENCY_MANAGEMENT || context == PomTemplateContext.PROJECT) {
      //now add the proposal for dependency inclusion
      Region region = new Region(request.getReplacementBeginPosition(), 0);
      InsertArtifactProposal.Configuration config = new InsertArtifactProposal.Configuration(
          InsertArtifactProposal.SearchType.DEPENDENCY);
      config.setCurrentNode(node);

      request.addProposal(new InsertArtifactProposal(sourceViewer, region, config));
    }

    if(context == PomTemplateContext.PLUGINS || context == PomTemplateContext.BUILD
        || context == PomTemplateContext.PLUGIN_MANAGEMENT || context == PomTemplateContext.PROJECT) {
      //now add the proposal for plugin inclusion
      Region region = new Region(request.getReplacementBeginPosition(), 0);
      InsertArtifactProposal.Configuration config = new InsertArtifactProposal.Configuration(
          InsertArtifactProposal.SearchType.PLUGIN);
      config.setCurrentNode(node);

      request.addProposal(new InsertArtifactProposal(sourceViewer, region, config));

    }
    //comes after dependency and plugin.. the dep and plugin ones are guessed to be more likely hits..
    if(context == PomTemplateContext.PROJECT) {
      //check if we have a parent defined..
      Node project = node;
      if(project != null && project instanceof Element) {
        Element parent = XmlUtils.findChild((Element) project, "parent"); //$NON-NLS-1$
        if(parent == null) {
          //now add the proposal for parent inclusion
          Region region = new Region(request.getReplacementBeginPosition(), 0);
          Element groupId = XmlUtils.findChild((Element) project, "groupId"); //$NON-NLS-1$
          String groupString = null;
          if(groupId != null) {
            groupString = XmlUtils.getTextValue(groupId);
          }
          InsertArtifactProposal.Configuration config = new InsertArtifactProposal.Configuration(
              InsertArtifactProposal.SearchType.PARENT);
          config.setInitiaSearchString(groupString);
          request.addProposal(new InsertArtifactProposal(sourceViewer, region, config));
        }
      }
    }
    if((context == PomTemplateContext.PROJECT && XmlUtils.findChild((Element) node, "licenses") == null)
        || context == PomTemplateContext.LICENSES) {
      Region region = new Region(request.getReplacementBeginPosition(), 0);
      request.addProposal(new InsertSPDXLicenseProposal(sourceViewer, context, region));
    }
  }

  private static String findRelativePath(ITextViewer viewer, Element parent) {
    String groupId = XmlUtils.getTextValue(XmlUtils.findChild(parent, "groupId")); //$NON-NLS-1$
    String artifactId = XmlUtils.getTextValue(XmlUtils.findChild(parent, "artifactId")); //$NON-NLS-1$
    String version = XmlUtils.getTextValue(XmlUtils.findChild(parent, "version")); //$NON-NLS-1$
    return findRelativePath(viewer, groupId, artifactId, version);
  }

  public static String findRelativePath(ITextViewer viewer, String groupId, String artifactId, String version) {
    if(groupId != null && artifactId != null && version != null) {
      IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().getMavenProject(groupId, artifactId, version);
      if(facade != null) {
        //now add the proposal for relativePath
        IFile parentPomFile = facade.getPom();
        IPath path = parentPomFile.getLocation();
        //TODO we might not need the IPRoject instance at all..
        IProject prj = XmlUtils.extractProject(viewer);
        if(prj != null && path != null) {
          IPath path2 = prj.getLocation();
          IPath relative = path.makeRelativeTo(path2);
          if(relative != path) {
            return relative.toString();
          }
        }
      }
    }
    return null;
  }

  private void addTemplateProposals(ContentAssistRequest request, PomTemplateContext context, ITextViewer sourceViewer,
      boolean tagProposals) {
    MavenProject prj = XmlUtils.extractMavenProject(sourceViewer);
    IProject eclipseprj = XmlUtils.extractProject(sourceViewer);
    ITextSelection selection = (ITextSelection) sourceViewer.getSelectionProvider().getSelection();

    Node parentNode = request.getParent();
    int offset = request.getReplacementBeginPosition();
    String prefix = request.getMatchString();
    int len = prefix.length();

    // replace text until the next whitespace or tag end
    IndexedRegion ir = (IndexedRegion) request.getNode();
    if(ir instanceof Text) {
      IDocument document = sourceViewer.getDocument();
      for(int i = offset + len; i < ir.getEndOffset(); i++ ) {
        try {
          if(Character.isWhitespace(document.getChar(i))) {
            break;
          }
        } catch(BadLocationException e) {
          break;
        }
        len++ ;
      }
    }

    // also replace opening '<'
    if(tagProposals) {
      offset-- ;
      len++ ;
    }

    Region region = new Region(offset, len);
    TemplateContext templateContext = createContext(sourceViewer, region, context.getContextTypeId());
    if(templateContext == null) {
      return;
    }

    // name of the selection variables {line, word}_selection 
    templateContext.setVariable("selection", selection.getText()); //$NON-NLS-1$

    // add the user defined templates - separate them from the rest of the templates
    // so that we know what they are and can assign proper icon to them.
    List<TemplateProposal> matches = new ArrayList<TemplateProposal>();
    TemplateStore store = MvnIndexPlugin.getDefault().getTemplateStore();
    if(store != null) {
      Template[] templates = store.getTemplates(context.getContextTypeId());
      for(Template template : templates) {
        TemplateProposal proposal = createProposalForTemplate(prefix, region, templateContext,
            MvnImages.IMG_USER_TEMPLATE, template, true);
        if(proposal != null) {
          matches.add(proposal);
        }
      }
    }

    Template[] templates = context.getTemplates(prj, eclipseprj, parentNode, prefix);
    for(Template template : templates) {
      Image image = null;

      if(template instanceof PomTemplate) {
        image = ((PomTemplate) template).getImage();
      }

      TemplateProposal proposal = createProposalForTemplate(prefix, region, templateContext, image, template, false);
      if(proposal != null) {
        matches.add(proposal);
      }
    }

    for(ICompletionProposal proposal : matches) {
      request.addProposal(proposal);
    }
  }

  private TemplateProposal createProposalForTemplate(String prefix, Region region, TemplateContext context, Image image,
      final Template template, boolean isUserTemplate) {
    try {
      context.getContextType().validate(template.getPattern());
      if(template.matches(prefix, context.getContextType().getId())) {
        if(isUserTemplate) {
          //for templates defined by users, preserve the default behaviour..
          return new PomTemplateProposal(template, context, region, image, getRelevance(template, prefix)) {
            public String getAdditionalProposalInfo() {
              return StringUtils.convertToHTMLContent(super.getAdditionalProposalInfo());
            }
          };
        }
        return new PomTemplateProposal(template, context, region, image, getRelevance(template, prefix)) {
          public String getAdditionalProposalInfo() {
            return getTemplate().getDescription();
          }

          public String getDisplayString() {
            return template.getName();
          }
        };
      }
    } catch(TemplateException e) {
      // ignore
    }

    return null;
  }

  protected TemplateContext createContext(ITextViewer viewer, IRegion region, String contextTypeId) {
    TemplateContextType contextType = getContextType(viewer, region, contextTypeId);
    if(contextType != null) {
      IDocument document = viewer.getDocument();
      return new DocumentTemplateContext(contextType, document, region.getOffset(), region.getLength());
    }
    return null;
  }

  //TODO we should have different relevance for user defined templates and generated proposals..
  protected int getRelevance(Template template, String prefix) {
    if(template instanceof PomTemplate) {
      int rel = ((PomTemplate) template).getRelevance();
      if(rel != -1)
        return rel;
    }

    if(template.getName().startsWith(prefix))
      return 1900;
    return 1500;
  }

  protected TemplateContextType getContextType(ITextViewer viewer, IRegion region, String contextTypeId) {
    ContextTypeRegistry registry = MvnIndexPlugin.getDefault().getTemplateContextRegistry();
    if(registry != null) {
      return registry.getContextType(contextTypeId);
    }
    return null;
  }

  public static final String extractPrefix(ITextViewer viewer, int offset) {
    int i = offset;
    IDocument document = viewer.getDocument();
    if(i > document.getLength()) {
      return ""; //$NON-NLS-1$
    }

    try {
      while(i > 0) {
        char ch = document.getChar(i - 1);
        if(ch == '>' || ch == '<' || ch == ' ' || ch == '\n' || ch == '\t') {
          break;
        }
        i-- ;
      }
      return document.get(i, offset - i);
    } catch(BadLocationException e) {
      return ""; //$NON-NLS-1$
    }
  }

}
