content: package com.antfortune.freeline.idea.actions;
  
  import com.android.tools.idea.gradle.dsl.model.GradleBuildModel;
  import com.android.tools.idea.gradle.dsl.model.dependencies.ArtifactDependencyModel;
  import com.antfortune.freeline.idea.icons.PluginIcons;
  import com.intellij.openapi.application.ApplicationManager;
  import com.intellij.openapi.command.CommandProcessor;
  import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
  import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
  import com.intellij.openapi.project.Project;
  import com.intellij.openapi.vfs.VirtualFile;
  import com.antfortune.freeline.idea.models.ArtifactDependencyModelWrapper;
  import com.antfortune.freeline.idea.models.GradleDependencyEntity;
  import com.antfortune.freeline.idea.models.GetServerCallback;
  import com.antfortune.freeline.idea.models.GradleSyncHandler;
  import org.jetbrains.annotations.NotNull;
  import com.antfortune.freeline.idea.utils.*;
  import com.antfortune.freeline.idea.views.CheckUpdateDialog;
  
  import javax.swing.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.util.*;
  
  /**
   * Created by pengwei on 16/9/11.
   */
  public class UpdateAction extends BaseAction implements GetServerCallback {
  
      public UpdateAction() {
          super(PluginIcons.GradleSync);
      }
  
      @Override
      public void actionPerformed() {
          if (FreelineUtil.checkInstall(currentProject)) {
              asyncTask(new GetServerVersion(this));
          }
      }
  
      /**
       * 更新操作
       *
       * @param newVersion
       * @param gradleBuildModels
       */
      protected void updateAction(final String newVersion, final Map<GradleBuildModel,
              List<ArtifactDependencyModel>> gradleBuildModels) {
          CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
              @Override
              public void run() {
                  ApplicationManager.getApplication().runWriteAction(new Runnable() {
                      @Override
                      public void run() {
                          for (GradleBuildModel file : gradleBuildModels.keySet()) {
                              List<ArtifactDependencyModel> models = gradleBuildModels.get(file);
                              for (ArtifactDependencyModel dependencyModel1 : models) {
                                  ArtifactDependencyModelWrapper dependencyModel = new ArtifactDependencyModelWrapper(dependencyModel1);
                                  if (isClasspathLibrary(dependencyModel)) {
                                      dependencyModel1.setVersion(newVersion);
                                  }
                                  if (isDependencyLibrary(dependencyModel)) {
                                      file.dependencies().remove(dependencyModel1);
                                  }
                              }
                              file.applyChanges();
                          }
                          GradleUtil.executeTask(currentProject, "initFreeline", "-Pmirror", new ExternalSystemTaskNotificationListenerAdapter() {
                              @Override
                              public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) {
                                  super.onTaskOutput(id, text, stdOut);
                              }
                          });
                      }
                  });
              }
          });
      }
  
      /**
       * 处理结果
       *
       * @param entity
       * @param gradleBuildModels
       */
      private void resultHandle(final GradleDependencyEntity entity, final Map<GradleBuildModel,
              List<ArtifactDependencyModel>> gradleBuildModels) {
          String localVersion = null;
          StringBuilder builder = new StringBuilder();
          for (GradleBuildModel file : gradleBuildModels.keySet()) {
              List<ArtifactDependencyModel> models = gradleBuildModels.get(file);
              for (ArtifactDependencyModel dependencyModel1 : models) {
                  ArtifactDependencyModelWrapper dependencyModel = new ArtifactDependencyModelWrapper(dependencyModel1);
                  if (isClasspathLibrary(dependencyModel) || isDependencyLibrary(dependencyModel)) {
                      if (isClasspathLibrary(dependencyModel)) {
                          localVersion = dependencyModel.version();
                      }
                      builder.append(dependencyModel.configurationName()).append(" '")
                              .append(dependencyModel.group()).append(":")
                              .append(dependencyModel.name()).append(":")
                              .append(dependencyModel.version()).append("'")
                              .append("<br/>");
                  }
              }
          }
          if (Utils.notEmpty(localVersion)) {
              int compare = localVersion.compareTo(entity.getVersion());
              final CheckUpdateDialog dialog = new CheckUpdateDialog();
              dialog.getButtonOK().setEnabled(compare < 0);
              dialog.setServerVersion(entity.getGroupId(), entity.getArtifactId(), entity.getVersion());
              dialog.setServerUpdateTime(entity.getUpdateTime());
              dialog.setLocalVersion(builder.toString());
              dialog.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      updateAction(entity.getVersion(), gradleBuildModels);
                      dialog.dispose();
                  }
              });
              dialog.showDialog();
          } else {
              NotificationUtils.infoNotification("please add freeline dependency first");
          }
      }
  
      private boolean isClasspathLibrary(ArtifactDependencyModelWrapper model) {
          return model.configurationName().equals("classpath") &&
                  model.group().equals("com.antfortune.freeline") && model.name().equals("gradle");
      }
  
      private boolean isDependencyLibrary(ArtifactDependencyModelWrapper model) {
          return model.configurationName().endsWith("ompile") &&
                  model.group().equals("com.antfortune.freeline") && model.name().startsWith("runtime");
      }
  
      @Override
      public void onSuccess(final GradleDependencyEntity entity) {
          invokeLater(new Runnable() {
              @Override
              public void run() {
                  Collection<VirtualFile> gradleFiles = GradleUtil.getAllGradleFile(currentProject);
                  Map<GradleBuildModel, List<ArtifactDependencyModel>> fileListMap = new HashMap<GradleBuildModel, List<ArtifactDependencyModel>>();
                  for (VirtualFile file : gradleFiles) {
                      GradleBuildModel model = GradleBuildModel.parseBuildFile(file, currentProject);
                      if (model != null) {
                          List<ArtifactDependencyModel> classPaths = model.buildscript().dependencies().artifacts();
                          List<ArtifactDependencyModel> depends = model.dependencies().artifacts();
                          classPaths.addAll(depends);
                          fileListMap.put(model, classPaths);
                      }
                  }
                  resultHandle(entity, fileListMap);
              }
          });
      }
  
      @Override
      public void onFailure(String errMsg) {
          NotificationUtils.errorNotification("Update Freeline Failure: " + errMsg);
      }
  
      /**
       * 获取服务器最新版本
       */
      public static class GetServerVersion implements Runnable {
          private GetServerCallback callback;
  
          public GetServerVersion(GetServerCallback callback) {
              this.callback = callback;
          }
  
          @Override
          public void run() {
              if (this.callback == null) {
                  return;
              }
              try {
                  URL url = new URL("http://jcenter.bintray.com/com/antfortune/freeline/gradle/maven-metadata.xml");
                  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                  conn.setConnectTimeout(5 * 1000);
                  conn.setRequestMethod("GET");
                  InputStream inStream = conn.getInputStream();
                  String result = StreamUtil.inputStream2String(inStream);
                  if (result != null && result.trim().length() != 0) {
                      GradleDependencyEntity entity = GradleDependencyEntity.parse(result);
                      if (entity != null && Utils.notEmpty(entity.getVersion())
                              && Utils.notEmpty(entity.getGroupId())) {
                          this.callback.onSuccess(entity);
                      } else {
                          this.callback.onFailure("analytic failure");
                      }
                  } else {
                      this.callback.onFailure("response empty");
                  }
              } catch (IOException e) {
                  this.callback.onFailure(e.getMessage());
              }
          }
      }
  }
  