package com.linkedin.intellij.dust;

import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.linkedin.intellij.dust.psi.DustCloseTag;
import com.linkedin.intellij.dust.psi.DustOpenTag;
import com.linkedin.intellij.dust.psi.DustTypes;
import org.jetbrains.annotations.NotNull;

import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: yzhang
 * Date: 3/8/13
 * Time: 10:53 AM
 */
public class DustAnnotator implements Annotator {
  @Override
  public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
    if (element instanceof DustOpenTag) {
      DustOpenTag openTag = (DustOpenTag) element;
      checkMatchingCloseTag(openTag, holder);
    }

    if (element.getNode().getElementType() == DustTypes.COMMENT) {
      String commentStr = element.getText();

      if (commentStr.length() >= 8) {
        commentStr = commentStr.substring(0, commentStr.length() - 2);
        Pattern p = Pattern.compile("TODO[^\n]*");
        Matcher m = p.matcher(commentStr);

        int startOffset = element.getTextRange().getStartOffset();
        while (m.find()) {
          MatchResult mr = m.toMatchResult();
          TextRange tr = new TextRange(startOffset + mr.start(), startOffset + mr.end());
          holder.createInfoAnnotation(tr, null).setTextAttributes(DustSyntaxHighlighter.TODO);
        }
      }
    }
  }

  private static boolean checkMatchingCloseTag(DustOpenTag openTag, AnnotationHolder holder) {
    if (openTag == null) return false;

    String openTagName = getTagName(openTag);
    PsiElement sibling = openTag.getNextSibling();
    DustCloseTag closeTag = null;
    while (sibling != null) {
      if (sibling instanceof DustCloseTag) {
        closeTag = (DustCloseTag) sibling;
        if (getTagName(closeTag).equals(openTagName)) {
          return true;
        }
      }
      sibling = sibling.getNextSibling();
    }

    holder.createErrorAnnotation(openTag.getTextRange(), "Could not find matching closing tag " + getTagName(openTag));

    if (closeTag != null) {
      holder.createErrorAnnotation(closeTag.getTextRange(), "Could not find matching opening tag " + getTagName(closeTag));
    }

    return false;
  }

  private static String getTagName(PsiElement tag) {
    return tag.getChildren()[0].getText().trim();
  }
}