package jetbrains.mps.baseLanguage.javadoc.editor;

/*Generated by MPS */

import jetbrains.mps.openapi.editor.EditorContext;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.action.SNodeFactoryOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.editor.runtime.selection.SelectionUtil;
import jetbrains.mps.openapi.editor.selection.SelectionManager;
import jetbrains.mps.baseLanguage.behavior.IBLDeprecatable__BehaviorDescriptor;
import jetbrains.mps.util.Reference;
import jetbrains.mps.editor.runtime.commands.EditorCommand;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SInterfaceConcept;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SProperty;

public class TextCommentPartUtil {
  public TextCommentPartUtil() {
  }
  public static void processCellText(EditorContext editorContext, final SNode node, final String newText) {
    if (newText.startsWith("@")) {
      SNode comment = SNodeOperations.getNodeAncestor(node, CONCEPTS.BaseDocComment$bU, false, false);
      boolean isClassifier = SNodeOperations.isInstanceOf(comment, CONCEPTS.ClassifierDocComment$mh);
      boolean isMethod = SNodeOperations.isInstanceOf(comment, CONCEPTS.MethodDocComment$HI);

      SNode tag = null;
      try {
        if (newText.startsWith("@author ")) {
          tag = SNodeFactoryOperations.addNewChild(comment, LINKS.tags$stUD, CONCEPTS.AuthorBlockDocTag$jR);
          return;
        }
        if (newText.startsWith("@since ")) {
          tag = SNodeFactoryOperations.addNewChild(comment, LINKS.tags$stUD, CONCEPTS.SinceBlockDocTag$KR);
          return;
        }
        if (newText.startsWith("@version ")) {
          tag = SNodeFactoryOperations.addNewChild(comment, LINKS.tags$stUD, CONCEPTS.VersionBlockDocTag$wp);
          return;
        }
        if (newText.startsWith("@see ")) {
          tag = SNodeFactoryOperations.addNewChild(comment, LINKS.tags$stUD, CONCEPTS.SeeBlockDocTag$fI);
          return;
        }
        if (newText.startsWith("@param ") && isClassifier) {
          tag = SNodeFactoryOperations.addNewChild(SNodeOperations.getNodeAncestor(node, CONCEPTS.ClassifierDocComment$mh, false, false), LINKS.tags$stUD, CONCEPTS.ParameterBlockDocTag$ie);
          return;
        }
        if (newText.startsWith("@param ") && isMethod) {
          tag = SNodeFactoryOperations.addNewChild(SNodeOperations.getNodeAncestor(node, CONCEPTS.MethodDocComment$HI, false, false), LINKS.tags$stUD, CONCEPTS.ParameterBlockDocTag$ie);
          return;
        }
        if (newText.startsWith("@throws ") && isMethod) {
          tag = SNodeFactoryOperations.addNewChild(SNodeOperations.getNodeAncestor(node, CONCEPTS.MethodDocComment$HI, false, false), LINKS.tags$stUD, CONCEPTS.ThrowsBlockDocTag$bu);
          return;
        }
        if (newText.startsWith("@return ") && isMethod) {
          tag = SNodeFactoryOperations.addNewChild(SNodeOperations.getNodeAncestor(node, CONCEPTS.MethodDocComment$HI, false, false), LINKS.tags$stUD, CONCEPTS.ReturnBlockDocTag$KD);
          return;
        }

      } finally {
        if ((tag != null)) {
          SPropertyOperations.assign(node, PROPS.text$aOLd, "");
          DocTagHelper.organizeTags(comment);
          SelectionUtil.selectCell(editorContext, tag, SelectionManager.FIRST_EDITABLE_CELL);
        }
      }
      if (newText.startsWith("@deprecated ")) {
        IBLDeprecatable__BehaviorDescriptor.markDeprecated_id6Va_BJexupi.invoke(SNodeOperations.getNodeAncestor(node, CONCEPTS.IBLDeprecatable$ah, false, false));
        SNode deprecatedTag = SNodeFactoryOperations.addNewChild(comment, LINKS.tags$stUD, CONCEPTS.DeprecatedBlockDocTag$8n);
        SPropertyOperations.assign(node, PROPS.text$aOLd, "");
        DocTagHelper.organizeTags(comment);
        editorContext.selectWRTFocusPolicy(deprecatedTag);
        return;
      }
    }

    int index = newText.indexOf("{@");
    if (index != -1) {
      SNode tagPart;
      divideLineBetweenCaret(node, index, index + 2, newText);
      tagPart = SNodeFactoryOperations.createNewNode(CONCEPTS.InlineTagCommentLinePart$F9, null);
      SNodeOperations.insertNextSiblingChild(node, tagPart);
      editorContext.selectWRTFocusPolicy(tagPart);
      return;
    }
    index = newText.indexOf("{{");
    if (index != -1) {
      SNode codeSnippet;
      SNode nextLine = divideLineBetweenCaretAndInsertNewLine(node, index, index + 2, newText);
      codeSnippet = SNodeFactoryOperations.createNewNode(CONCEPTS.CodeSnippet$3G, null);
      SNodeOperations.insertPrevSiblingChild(nextLine, codeSnippet);
      editorContext.selectWRTFocusPolicy(codeSnippet);
      return;
    }
    index = newText.indexOf("<>");
    if (index != -1) {
      final int finalIndex = index;
      final Reference<SNode> htmlElement = new Reference();
      editorContext.getRepository().getModelAccess().executeCommand(new EditorCommand(editorContext) {
        protected void doExecute() {
          divideLineBetweenCaret(node, finalIndex, finalIndex + 1, newText);

          htmlElement.set(SNodeFactoryOperations.createNewNode(CONCEPTS.HTMLElement$SD, null));
          SNodeOperations.insertNextSiblingChild(node, htmlElement.get());
        }
      });
      editorContext.selectWRTFocusPolicy(htmlElement.get());
      return;
    }
  }
  public static void divideLineBetweenCaret(SNode node, int index1, int index2, String text) {
    String leftPart = text.substring(0, index1);
    String rightPart = text.substring(index2);

    SPropertyOperations.set(node, PROPS.text$aOLd, leftPart);

    SNode newTextPart = SNodeFactoryOperations.createNewNode(CONCEPTS.TextCommentLinePart$Eb, null);
    SPropertyOperations.set(newTextPart, PROPS.text$aOLd, rightPart);
    SNodeOperations.insertNextSiblingChild(node, newTextPart);
  }
  public static SNode divideLineBetweenCaretAndInsertNewLine(SNode node, int index1, int index2, String text) {
    String leftPart = text.substring(0, index1);
    String rightPart = text.substring(index2);

    SNode thisLine = SNodeOperations.cast(SNodeOperations.getParent(node), CONCEPTS.CommentLine$hJ);
    SNode nextLine = SNodeFactoryOperations.createNewNode(CONCEPTS.CommentLine$hJ, null);
    SNodeFactoryOperations.addNewChild(nextLine, LINKS.part$QuzQ, CONCEPTS.TextCommentLinePart$Eb);
    SPropertyOperations.assign(SNodeOperations.cast(ListSequence.fromList(SLinkOperations.getChildren(nextLine, LINKS.part$QuzQ)).getElement(0), CONCEPTS.TextCommentLinePart$Eb), PROPS.text$aOLd, rightPart);
    SNodeOperations.insertNextSiblingChild(thisLine, nextLine);

    int indexInParent = SNodeOperations.getIndexInParent(node);
    SPropertyOperations.assign(SNodeOperations.cast(ListSequence.fromList(SLinkOperations.getChildren(thisLine, LINKS.part$QuzQ)).getElement(indexInParent), CONCEPTS.TextCommentLinePart$Eb), PROPS.text$aOLd, leftPart);

    while (ListSequence.fromList(SLinkOperations.getChildren(thisLine, LINKS.part$QuzQ)).count() > indexInParent + 1) {
      SNode linePart = ListSequence.fromList(SLinkOperations.getChildren(thisLine, LINKS.part$QuzQ)).getElement(indexInParent + 1);
      SNodeOperations.deleteNode(linePart);
      ListSequence.fromList(SLinkOperations.getChildren(nextLine, LINKS.part$QuzQ)).addElement(linePart);
    }

    return nextLine;
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept BaseDocComment$bU = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x4a3c146b7fae70d3L, "jetbrains.mps.baseLanguage.javadoc.structure.BaseDocComment");
    /*package*/ static final SConcept ClassifierDocComment$mh = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x1cb65d9fe66a764cL, "jetbrains.mps.baseLanguage.javadoc.structure.ClassifierDocComment");
    /*package*/ static final SConcept MethodDocComment$HI = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x4a3c146b7faeeb34L, "jetbrains.mps.baseLanguage.javadoc.structure.MethodDocComment");
    /*package*/ static final SConcept AuthorBlockDocTag$jR = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x4a3c146b7faee13eL, "jetbrains.mps.baseLanguage.javadoc.structure.AuthorBlockDocTag");
    /*package*/ static final SConcept SinceBlockDocTag$KR = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c87ddadL, "jetbrains.mps.baseLanguage.javadoc.structure.SinceBlockDocTag");
    /*package*/ static final SConcept VersionBlockDocTag$wp = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c87dda0L, "jetbrains.mps.baseLanguage.javadoc.structure.VersionBlockDocTag");
    /*package*/ static final SConcept SeeBlockDocTag$fI = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x1ec532ec252ca3abL, "jetbrains.mps.baseLanguage.javadoc.structure.SeeBlockDocTag");
    /*package*/ static final SConcept ParameterBlockDocTag$ie = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c905f8aL, "jetbrains.mps.baseLanguage.javadoc.structure.ParameterBlockDocTag");
    /*package*/ static final SConcept ThrowsBlockDocTag$bu = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x514c0f68704ec270L, "jetbrains.mps.baseLanguage.javadoc.structure.ThrowsBlockDocTag");
    /*package*/ static final SConcept ReturnBlockDocTag$KD = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x514c0f687050918eL, "jetbrains.mps.baseLanguage.javadoc.structure.ReturnBlockDocTag");
    /*package*/ static final SInterfaceConcept IBLDeprecatable$ah = MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11d2ea8a339L, "jetbrains.mps.baseLanguage.structure.IBLDeprecatable");
    /*package*/ static final SConcept DeprecatedBlockDocTag$8n = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c87f964L, "jetbrains.mps.baseLanguage.javadoc.structure.DeprecatedBlockDocTag");
    /*package*/ static final SConcept InlineTagCommentLinePart$F9 = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x7c7f5b2f31990289L, "jetbrains.mps.baseLanguage.javadoc.structure.InlineTagCommentLinePart");
    /*package*/ static final SConcept CodeSnippet$3G = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x2398cefbc261e3ffL, "jetbrains.mps.baseLanguage.javadoc.structure.CodeSnippet");
    /*package*/ static final SConcept HTMLElement$SD = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x5bc4aa08e154b399L, "jetbrains.mps.baseLanguage.javadoc.structure.HTMLElement");
    /*package*/ static final SConcept TextCommentLinePart$Eb = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x7c7f5b2f31990287L, "jetbrains.mps.baseLanguage.javadoc.structure.TextCommentLinePart");
    /*package*/ static final SConcept CommentLine$hJ = MetaAdapterFactory.getConcept(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c87f96cL, "jetbrains.mps.baseLanguage.javadoc.structure.CommentLine");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink tags$stUD = MetaAdapterFactory.getContainmentLink(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x4a3c146b7fae70d3L, 0x4ab5c2019ddc99f3L, "tags");
    /*package*/ static final SContainmentLink part$QuzQ = MetaAdapterFactory.getContainmentLink(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x757ba20a4c87f96cL, 0x7c7f5b2f3199028dL, "part");
  }

  private static final class PROPS {
    /*package*/ static final SProperty text$aOLd = MetaAdapterFactory.getProperty(0xf280165065d5424eL, 0xbb1b463a8781b786L, 0x7c7f5b2f31990287L, 0x7c7f5b2f31990288L, "text");
  }
}
