content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 com.alibaba.compileflow.idea.plugin.provider.fileeditor;
  
  import java.beans.PropertyChangeListener;
  
  import javax.swing.*;
  
  import com.alibaba.compileflow.idea.graph.codec.ModelConvertFactory;
  import com.alibaba.compileflow.idea.graph.model.BpmModel;
  import com.alibaba.compileflow.idea.graph.model.checker.ModelCheckerMgr;
  import com.alibaba.compileflow.idea.plugin.lang.Lang;
  
  import com.google.gson.Gson;
  import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
  import com.intellij.ide.highlighter.JavaFileType;
  import com.intellij.ide.structureView.StructureViewBuilder;
  import com.intellij.openapi.application.ApplicationManager;
  import com.intellij.openapi.diagnostic.Logger;
  import com.intellij.openapi.editor.Document;
  import com.intellij.openapi.editor.Editor;
  import com.intellij.openapi.editor.EditorFactory;
  import com.intellij.openapi.fileEditor.FileEditor;
  import com.intellij.openapi.fileEditor.FileEditorLocation;
  import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
  import com.intellij.openapi.fileEditor.FileEditorManagerListener;
  import com.intellij.openapi.fileEditor.FileEditorState;
  import com.intellij.openapi.fileEditor.FileEditorStateLevel;
  import com.intellij.openapi.project.Project;
  import com.intellij.openapi.util.Key;
  import com.intellij.openapi.util.UserDataHolderBase;
  import com.intellij.openapi.vfs.VirtualFile;
  import com.intellij.psi.PsiFile;
  import com.intellij.util.messages.MessageBus;
  import org.jetbrains.annotations.NotNull;
  import org.jetbrains.annotations.Nullable;
  
  /**
   * show the javacode
   *
   * @author xuan
   * @since 2021-06-22
   */
  public class JavaSourceFileEditor extends UserDataHolderBase implements FileEditor {
      private static final String LINE_BREAK = "\n";
  
      private static final Logger logger = Logger.getInstance(JavaSourceFileEditor.class);
      private Project project;
      private Editor editor;
      private PsiFile psiFile;
      private Document document;
  
      public JavaSourceFileEditor(final Project project, PsiFile psiFile) {
          this.project = project;
          this.psiFile = psiFile;
          this.document = EditorFactory.getInstance().createDocument("");
          this.editor = EditorFactory.getInstance().createEditor(document, project, JavaFileType.INSTANCE, true);
  
          ApplicationManager.getApplication().invokeLater(this::loadJavaCode);
          // Monitor file changes
          MessageBus messageBus = project.getMessageBus();
          messageBus.connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener
              () {
              @Override
              public void selectionChanged(@NotNull FileEditorManagerEvent event) {
                  ApplicationManager.getApplication().invokeLater(() -> loadJavaCode());
              }
          });
      }
  
      private void loadJavaCode() {
          String javaCode;
          BpmModel bpmModel = null;
          try {
              // Empty file
              if (psiFile.getText().length() == 0) {
                  javaCode = "// Please draw bpm flow first, thanks!!!";
              } else {
                  bpmModel = ModelConvertFactory.getModelXmlConvertExt(psiFile.getVirtualFile().getExtension()).toModel(
                      psiFile.getText());
                  javaCode = ModelConvertFactory.getModelCodeConvertExt(psiFile.getVirtualFile().getExtension())
                      .getJavaCode(bpmModel, psiFile.getText());
              }
          } catch (Throwable e) {
              logger.error(e);
  
              javaCode = "//Bpm file is illegal. Message:";
              javaCode += LINE_BREAK;
              javaCode += e.getMessage();
              javaCode += LINE_BREAK;
  
              javaCode += "//Bpm file is illegal. Throwable:";
              javaCode += LINE_BREAK;
              javaCode += new Gson().toJson(e);
              javaCode += LINE_BREAK;
  
              javaCode += "//Ops... I found some problems. Please confirm:";
              javaCode += LINE_BREAK;
              javaCode += ModelCheckerMgr.check(bpmModel);
          }
  
          if (null == javaCode) {
              javaCode = "Just not support!!!";
          }
  
          refreshText(javaCode);
      }
  
      private void refreshText(String text) {
          ApplicationManager.getApplication().runWriteAction(
              () -> document.setText(text));
      }
  
      @NotNull
      @Override
      public JComponent getComponent() {
          return editor.getComponent();
      }
  
      @Nullable
      @Override
      public JComponent getPreferredFocusedComponent() {
          return editor.getComponent();
      }
  
      @NotNull
      @Override
      public String getName() {
          return "JavaCode";
      }
  
      @NotNull
      @Override
      public FileEditorState getState(@NotNull FileEditorStateLevel fileEditorStateLevel) {
          return ((o, l) -> false);
      }
  
      @Override
      public void setState(@NotNull FileEditorState fileEditorState) {
  
      }
  
      @Override
      public boolean isModified() {
          return false;
      }
  
      @Override
      public boolean isValid() {
          return true;
      }
  
      @Override
      public void selectNotify() {
  
      }
  
      @Override
      public void deselectNotify() {
  
      }
  
      @Override
      public void addPropertyChangeListener(@NotNull PropertyChangeListener propertyChangeListener) {
  
      }
  
      @Override
      public void removePropertyChangeListener(@NotNull PropertyChangeListener propertyChangeListener) {
  
      }
  
      @Nullable
      @Override
      public BackgroundEditorHighlighter getBackgroundHighlighter() {
          return null;
      }
  
      @Nullable
      @Override
      public FileEditorLocation getCurrentLocation() {
          return null;
      }
  
      @Nullable
      @Override
      public StructureViewBuilder getStructureViewBuilder() {
          return null;
      }
  
      @Override
      public void dispose() {
      }
  
      @Nullable
      @Override
      public <T> T getUserData(@NotNull Key<T> key) {
          return null;
      }
  
      @Override
      public <T> void putUserData(@NotNull Key<T> key, @Nullable T t) {
  
      }
  
      @Nullable
      @Override
      public VirtualFile getFile() {
          return psiFile.getVirtualFile();
      }
  
  }
  