/*
 * Copyright 2007 Sascha Weinreuter
 *
 * 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 org.intellij.plugins.relaxNG.validation;

import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.ExternalAnnotator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import org.intellij.plugins.relaxNG.ApplicationLoader;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.model.resolve.RelaxIncludeIndex;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: sweinreuter
 * Date: 18.07.2007
 */
public class RngSchemaValidator extends ExternalAnnotator<RngSchemaValidator.MyValidationMessageConsumer,RngSchemaValidator.MyValidationMessageConsumer> {
  private static final Logger LOG = Logger.getInstance(RngSchemaValidator.class.getName());

  @Nullable
  @Override
  public MyValidationMessageConsumer collectInformation(@NotNull final PsiFile file) {
    final FileType type = file.getFileType();
    if (type != StdFileTypes.XML && type != RncFileType.getInstance()) {
      return null;
    }
    final XmlFile xmlfile = (XmlFile)file;
    final XmlDocument document = xmlfile.getDocument();
    if (document == null) {
      return null;
    }
    if (type == StdFileTypes.XML) {
      final XmlTag rootTag = document.getRootTag();
      if (rootTag == null) {
        return null;
      }
      if (!ApplicationLoader.RNG_NAMESPACE.equals(rootTag.getNamespace())) {
        return null;
      }
    } else {
      if (!ApplicationManager.getApplication().isUnitTestMode() && MyErrorFinder.hasError(xmlfile)) {
        return null;
      }
    }
    final Document doc = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);

    final MyValidationMessageConsumer consumer = new MyValidationMessageConsumer();
    ErrorHandler eh = new DefaultHandler() {
      @Override
      public void warning(SAXParseException e) {
        handleError(e, file, doc, consumer.warning());
      }

      @Override
      public void error(SAXParseException e) {
        handleError(e, file, doc, consumer.error());
      }
    };

    RngParser.parsePattern(file, eh, true);
    return consumer;
  }

  @Nullable
  @Override
  public MyValidationMessageConsumer doAnnotate(MyValidationMessageConsumer collectedInfo) {
    return collectedInfo;
  }

  @Override
  public void apply(@NotNull PsiFile file,
                    MyValidationMessageConsumer annotationResult,
                    @NotNull AnnotationHolder holder) {
    annotationResult.apply(holder);
  }

  static class MyValidationMessageConsumer  {
    final List<Pair<PsiElement, String >> errors = new ArrayList<Pair<PsiElement, String>>();
    final List<Pair<PsiElement, String >> warnings = new ArrayList<Pair<PsiElement, String>>();
    ValidationMessageConsumer error() {
      return new ValidationMessageConsumer() {
        @Override
        public void onMessage(PsiElement context, String message) {
          errors.add(Pair.create(context, message));
        }
      }; 
    }
    ValidationMessageConsumer warning() {
      return new ValidationMessageConsumer() {
        @Override
        public void onMessage(PsiElement context, String message) {
          warnings.add(Pair.create(context, message));
        }
      }; 
    }
    void apply(AnnotationHolder holder) {
      MessageConsumerImpl errorc = new ErrorMessageConsumer(holder);
      MessageConsumerImpl warningc = new WarningMessageConsumer(holder);
      for (Pair<PsiElement, String> error : errors) {
        errorc.onMessage(error.first, error.second);
      }
      for (Pair<PsiElement, String> warning : warnings) {
        warningc.onMessage(warning.first, warning.second);
      }
    }
  }

  public static void handleError(SAXParseException ex, PsiFile file, Document document, ValidationMessageConsumer consumer) {
    final String systemId = ex.getSystemId();
    if (LOG.isDebugEnabled()) {
      LOG.debug("RNG Schema error: " + ex.getMessage() + " [" + systemId + "]");
    }

    if (systemId != null) {
      final VirtualFile virtualFile = findVirtualFile(systemId);
      if (!Comparing.equal(virtualFile, file.getVirtualFile())) {
        return;
      }
    }

    final PsiElement at;
    final int line = ex.getLineNumber();
    if (line > 0) {
      final int column = ex.getColumnNumber();
      final int startOffset = document.getLineStartOffset(line - 1);

      if (column > 0) {
        if (file.getFileType() == RncFileType.getInstance()) {
          final PsiElement e = file.findElementAt(startOffset + column);
          if (e == null) {
            at = e;
          } else {
            at = file.findElementAt(startOffset + column - 1);
          }
        } else {
          at = file.findElementAt(startOffset + column - 2);
        }
      } else {
        final PsiElement e = file.findElementAt(startOffset);
        at = e != null ? PsiTreeUtil.nextLeaf(e) : null;
      }
    } else {
      final XmlDocument d = ((XmlFile)file).getDocument();
      assert d != null;
      final XmlTag rootTag = d.getRootTag();
      assert rootTag != null;
      at = rootTag.getFirstChild();
    }

    final PsiElement host;
    if (file instanceof RncFile) {
      host = at;
    } else {
      host = PsiTreeUtil.getParentOfType(at, XmlAttribute.class, XmlTag.class);
    }
    if (at != null && host != null) {
      consumer.onMessage(host, ex.getMessage());
    } else {
      consumer.onMessage(file, ex.getMessage());
    }
  }

  public static VirtualFile findVirtualFile(String systemId) {
    try {
      return VfsUtil.findFileByURL(new URL(systemId));
    } catch (Exception e) {
      LOG.warn("Failed to build file from uri <" + systemId + ">", e);
      return VirtualFileManager.getInstance().findFileByUrl(VfsUtilCore.fixURLforIDEA(systemId));
    }
  }

  public interface ValidationMessageConsumer {
    void onMessage(PsiElement context, String message);
  }

  private abstract static class MessageConsumerImpl implements ValidationMessageConsumer {
    protected final AnnotationHolder myHolder;

    public MessageConsumerImpl(AnnotationHolder holder) {
      myHolder = holder;
    }

    @Override
    public void onMessage(PsiElement host, String message) {
      final ASTNode node = host.getNode();
      assert node != null;

      if (host instanceof XmlAttribute) {
        final ASTNode nameNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
        createAnnotation(nameNode, message);
      } else if (host instanceof XmlTag) {
        final ASTNode start = XmlChildRole.START_TAG_NAME_FINDER.findChild(node);
        if (start != null) {
          createAnnotation(start, message);
        }

        final ASTNode end = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(node);
        if (end != null) {
          createAnnotation(end, message);
        }
      } else {
        createAnnotation(node, message);
      }
    }

    protected abstract void createAnnotation(ASTNode node, String message);
  }

  private static class ErrorMessageConsumer extends MessageConsumerImpl {
    @NonNls
    private static final String MISSING_START_ELEMENT = "missing \"start\" element";
    private static final String UNDEFINED_PATTERN = "reference to undefined pattern ";

    public ErrorMessageConsumer(AnnotationHolder holder) {
      super(holder);
    }

    @Override
    protected void createAnnotation(ASTNode node, String message) {
      if (MISSING_START_ELEMENT.equals(message)) {
        final PsiFile psiFile = node.getPsi().getContainingFile();
        if (psiFile instanceof XmlFile) {
          final PsiElementProcessor.FindElement<XmlFile> processor = new PsiElementProcessor.FindElement<XmlFile>();
          RelaxIncludeIndex.processBackwardDependencies((XmlFile)psiFile, processor);
          if (processor.isFound()) {
            // files that are included from other files do not need a <start> element.
            myHolder.createWeakWarningAnnotation(node, message);
            return;
          }
        }
      } else if (message != null && message.startsWith(UNDEFINED_PATTERN)) {
        // we've got our own validation for that
        return;
      }
      myHolder.createErrorAnnotation(node, message);
    }
  }

  private static class WarningMessageConsumer extends MessageConsumerImpl {

    public WarningMessageConsumer(AnnotationHolder holder) {
      super(holder);
    }

    @Override
    protected void createAnnotation(ASTNode node, String message) {
      myHolder.createWarningAnnotation(node, message);
    }
  }

  private static class MyErrorFinder extends PsiRecursiveElementVisitor {
    private static final MyErrorFinder INSTANCE = new MyErrorFinder();

    private static final class HasError extends RuntimeException {
    }
    private static final HasError FOUND = new HasError();

    @Override
    public void visitErrorElement(PsiErrorElement element) {
      throw FOUND;
    }

    public static boolean hasError(PsiElement element) {
      try {
        element.accept(INSTANCE);
        return false;
      } catch (HasError e) {
        return true;
      }
    }
  }

}
