/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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 com.google.appindexing.fetchasgoogle;

import static com.google.wireless.android.sdk.stats.GradleSyncStats.Trigger.TRIGGER_BUILD_BEFORE_BUILDING_APK;

import com.android.annotations.VisibleForTesting;
import com.android.build.OutputFile;
import com.android.builder.model.AndroidArtifact;
import com.android.builder.model.AndroidArtifactOutput;
import com.android.tools.idea.gradle.project.build.invoker.GradleBuildInvoker;
import com.android.tools.idea.gradle.project.build.invoker.GradleInvocationResult;
import com.android.tools.idea.gradle.project.build.invoker.TestCompileType;
import com.android.tools.idea.gradle.project.model.AndroidModuleModel;
import com.android.tools.idea.gradle.project.sync.GradleSyncInvoker;
import com.android.tools.idea.gradle.project.sync.GradleSyncListener;
import com.android.tools.idea.gradle.project.sync.GradleSyncState;
import com.android.tools.idea.model.AndroidModel;
import com.google.api.services.fetchasgoogle_pa.model.ApkHolder;
import com.google.api.services.fetchasgoogle_pa.model.FetchResponse;
import com.google.appindexing.editor.AppIndexingVirtualFile;
import com.google.appindexing.fetchasgoogle.FetchAsGoogleClient.FetchAsGoogleException;
import com.google.appindexing.util.AppIndexingBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ThreeState;
import com.intellij.util.concurrency.Semaphore;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * A runnable task which execute a Fetch as Google request, including building apk, uploading and fetching result.
 */
public class FetchAsGoogleTask implements Runnable {
  private static final Logger logger = Logger.getInstance(FetchAsGoogleTask.class);
  private final boolean myBuildApkToRun;
  private final RequestType myRequestType;

  private Status myStatus = Status.NOT_STARTED;
  private ErrorCode myErrorCode;
  private Project myProject;
  private String myDeepLink;
  private AppIndexingVirtualFile myVirtualFile;
  private FetchAsGoogleClient myFetchAsGoogleClient;
  private ApkHolder myApkHolder;
  private FetchResponse myFetchResponse;
  private Date myCreatedTime;
  private UploadedApkManager myUploadedApkManager;
  private Helper myHelper;
  private String myPackageId;


  /**
   * @return package id of the app for test. It could be null if the package id is failed to get from app manifest file.
   */
  @Nullable
  public String getPackageId() {
    return myPackageId;
  }

  @NotNull
  public RequestType getRequestType() {
    return myRequestType;
  }

  public enum Status {
    NOT_STARTED,
    BUILDING_APK, // Building the apk
    UPLOADING_APK, // Uploading the apk to backend server.
    FETCHING_RESULT, // Waiting the result.
    SUCCESS,
    FAIL
  }

  public enum ErrorCode {
    UNKNOWN,
    BUILD_APK_FAILED,
    UPLOAD_APK_FAILED,
    FETCH_RESULT_FAILED,
    NEED_SIGNIN,
    NETWORK_ERROR,
    URI_NOT_SUPPORTED,
    UNKNOWN_URL,
    UNKNOWN_APP_URI,
    APK_NOT_FOUND,
    BLACKLISTED_URL,
    URL_INDEX_ERROR,
    EMPTY_PACKAGE_ID,

    // Error codes for checking app indexing errors
    USER_ACTION_LOGGING_ERROR,
    PERSONAL_CONTENT_INDEXING_ERROR,
    BACKEND_ERROR,
    RESOURCE_EXHAUSTED,
    NOT_FOUND,
    APP_OWNERSHIP_VERIFICATION_FAILED,
    OK;

    private final String message;

    ErrorCode() {
      this.message = AppIndexingBundle.message("app.indexing.fetch.as.google.test.error." + name());
    }


    public String getName() {
      return super.name();
    }

    public String getMessage() {
      return message;
    }
  }

  public enum RequestType {
    UNKNOWN_PREVIEW_FEATURE,
    APP_INDEXING,
    INSTANT_APP,
    USER_ACTION_LOGGING_DEBUGGING,
    PERSONAL_CONTENT_INDEXING_DEBUGGING
  }

  static public FetchAsGoogleTask createFetchAsGoogleTask(
    @NotNull Project project, @NotNull Module module, @NotNull String deepLink, boolean buildApk, @NotNull RequestType type)
    throws FetchAsGoogleException {
    return new FetchAsGoogleTask(
      project, deepLink, FetchAsGoogleClient.createInstance(), UploadedApkManager.INSTANCE, new Helper(project, module), buildApk, type);
  }

  @VisibleForTesting
  FetchAsGoogleTask(@NotNull Project project, @NotNull String deepLink,
                    @NotNull FetchAsGoogleClient fetchAsGoogleClient, @NotNull UploadedApkManager uploadedApkManager,
                    @NotNull Helper helper, boolean buildApk, @NotNull RequestType type) {
    myProject = project;
    myDeepLink = deepLink;
    myCreatedTime = new Date();
    myFetchAsGoogleClient = fetchAsGoogleClient;
    myUploadedApkManager = uploadedApkManager;
    myHelper = helper;
    myBuildApkToRun = buildApk;
    myRequestType = type;
  }

  @NotNull
  public Status getStatus() {
    return myStatus;
  }

  @NotNull
  public Module getModule() {
    return myHelper.myModule;
  }

  @NotNull
  public Project getProject() {
    return myProject;
  }

  /**
   * @return error code of the task. If there is no error, just return null.
   */
  @Nullable
  public ErrorCode getErrorCode() {
    return myErrorCode;
  }

  @NotNull
  public Date getCreatedTime() {
    return myCreatedTime;
  }

  @Nullable
  public FetchResponse getFetchResponse() {
    return myFetchResponse;
  }

  private void changeStatus(@NotNull Status newStatus) {
    changeStatus(newStatus, null);
  }

  /**
   * Notify Result Panel of the latest status of the task to update UI.
   */
  private void changeStatus(@NotNull Status newStatus, @Nullable ErrorCode errorCode) {
    myStatus = newStatus;
    if (errorCode != null) {
      myErrorCode = errorCode;
    }
    Logger.getInstance(FetchAsGoogleTask.class).warn(newStatus.toString());
    ApplicationManager.getApplication().invokeAndWait(() -> myVirtualFile.fireContentChange(), ModalityState.any());
  }

  @Override
  public void run() {
    myVirtualFile = new AppIndexingVirtualFile(myDeepLink, this);
    ApplicationManager.getApplication().invokeAndWait(() -> {
      FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
      fileEditorManager.openFile(myVirtualFile, true);
    }, ModalityState.any());
    try {
      if (RequestType.PERSONAL_CONTENT_INDEXING_DEBUGGING == myRequestType ||
          RequestType.USER_ACTION_LOGGING_DEBUGGING == myRequestType) {
        changeStatus(Status.FETCHING_RESULT);
        myPackageId = myHelper.getPackageId();
        if (myPackageId != null) {
          myFetchResponse = myFetchAsGoogleClient.getAppIndexingErrorStats(myPackageId, myRequestType);
          changeStatus(Status.SUCCESS, ErrorCode.valueOf(myFetchResponse.getStatus()));
        }
        else {
          changeStatus(Status.FAIL, ErrorCode.EMPTY_PACKAGE_ID);
        }
        return;
      }

      // For app indexing preview
      if (myBuildApkToRun) {
        changeStatus(Status.BUILDING_APK);
        if (!myHelper.buildApk()) {
          changeStatus(Status.FAIL, ErrorCode.BUILD_APK_FAILED);
          return;
        }
        changeStatus(Status.UPLOADING_APK);
        if (!uploadApkIfNeeded()) {
          changeStatus(Status.FAIL, ErrorCode.UPLOAD_APK_FAILED);
          return;
        }
        changeStatus(Status.FETCHING_RESULT);
        myPackageId = myApkHolder.getApk().getPackageId();
        myFetchResponse =
          myFetchAsGoogleClient
            .fetchAsGoogle(myDeepLink, myPackageId, myApkHolder.getApk().getApkId(), RequestType.APP_INDEXING);
      }
      else {
        // Will use apk from Play Store for test.
        changeStatus(Status.FETCHING_RESULT);
        myPackageId = myHelper.getPackageId();
        if (StringUtil.isNotEmpty(myPackageId)) {
          myFetchResponse = myFetchAsGoogleClient.fetchAsGoogle(myDeepLink, myPackageId, null, myRequestType);
          Logger.getInstance(FetchAsGoogleTask.class).warn(myFetchResponse.getStatus());
        }
        else {
          changeStatus(Status.FAIL, ErrorCode.FETCH_RESULT_FAILED);
          return;
        }
      }

      changeStatus(Status.SUCCESS);
    }
    catch (FetchAsGoogleException e) {
      changeStatus(Status.FAIL, e.getErrorCode());
      logger.warn(e);
    }
    catch (IOException ex) {
      changeStatus(Status.FAIL, ErrorCode.NETWORK_ERROR);
      logger.warn(ex);
    }
    catch (Exception exx) {
      changeStatus(Status.FAIL, ErrorCode.UNKNOWN);
      logger.warn(exx);
    }
  }

  private boolean uploadApkIfNeeded() throws FetchAsGoogleException, IOException {
    File apkFile = myHelper.getApkFile();
    if (apkFile == null || !apkFile.exists()) {
      return false;
    }

    String packageId = myHelper.getPackageId();
    if (packageId == null || packageId.isEmpty()) {
      return false;
    }

    byte[] apkHash = myUploadedApkManager.hashApk(apkFile);
    if (apkHash == null) {
      logger.warn("Couldn't get apk file hash");
      return false;
    }

    myApkHolder = myUploadedApkManager.getApkHolder(apkHash);
    if (myApkHolder == null) {
      // Null means that the apk haven't been uploaded previously.
      myApkHolder = myFetchAsGoogleClient.uploadApk(packageId, apkFile);
      myUploadedApkManager.addUploadedApk(apkHash, myApkHolder);
    }
    return true;
  }

  /**
   * An helper class which wrap some logic. So we can mock them in test case.
   */
  static class Helper {
    private Project myProject;
    private Module myModule;
    private static final Logger logger = Logger.getInstance(Helper.class);

    public Helper(@NotNull Project project, @NotNull Module module) {
      myProject = project;
      myModule = module;
    }

    /**
     * Builds the APK file, return whether the build is successful.
     */
    public boolean buildApk() {
      // We reference the code in MakeBeforeRunTaskProvider#executeTask to write this method.
      final AtomicBoolean success = new AtomicBoolean();
      try {
        final Semaphore done = new Semaphore();
        done.down();

        final AtomicReference<String> errorMsgRef = new AtomicReference<>();

        // If the model needs a sync, we need to sync "synchronously" before running.
        // See: https://code.google.com/p/android/issues/detail?id=70718
        GradleSyncState syncState = GradleSyncState.getInstance(myProject);
        if (syncState.isSyncNeeded() != ThreeState.NO) {
          GradleSyncInvoker.Request request = new GradleSyncInvoker.Request(TRIGGER_BUILD_BEFORE_BUILDING_APK);
          request.runInBackground = false;
          GradleSyncInvoker.getInstance().requestProjectSync(myProject, request, new GradleSyncListener() {
            @Override
            public void syncFailed(@NotNull Project project, @NotNull String errorMessage) {
              errorMsgRef.set(errorMessage);
            }
          });
        }

        String errorMsg = errorMsgRef.get();
        if (errorMsg != null) {
          // Sync failed. There is no point on continuing, because most likely the model is either not there, or has stale information,
          // including the path of the APK.
          logger.warn("Unable to launch task. Project sync failed with message: " + errorMsg);
          return false;
        }

        final GradleBuildInvoker gradleBuildInvoker = GradleBuildInvoker.getInstance(myProject);
        final GradleBuildInvoker.AfterGradleInvocationTask afterTask = new GradleBuildInvoker.AfterGradleInvocationTask() {
          @Override
          public void execute(@NotNull GradleInvocationResult result) {
            success.set(result.isBuildSuccessful());
            gradleBuildInvoker.remove(this);
            done.up();
          }
        };

        if (myProject.isDisposed()) {
          done.up();
        }
        else {
          ApplicationManager.getApplication().invokeAndWait(() -> {
            gradleBuildInvoker.add(afterTask);
            gradleBuildInvoker.assemble(new Module[]{myModule}, TestCompileType.ALL);
          }, ModalityState.NON_MODAL);
          done.waitFor();
        }
      }
      catch (Throwable t) {
        return false;
      }
      return success.get();
    }

    @Nullable
    public File getApkFile() {
      File apkFile = null;
      AndroidFacet facet = AndroidFacet.getInstance(myModule);
      if (facet != null) {
        AndroidModuleModel model = AndroidModuleModel.get(facet);
        if (model != null) {
          AndroidArtifact artifact = model.getMainArtifact();
          for (AndroidArtifactOutput output : artifact.getOutputs()) {
            OutputFile file = output.getMainOutputFile();
            apkFile = file.getOutputFile();
          }
        }
      }
      return apkFile;
    }

    @Nullable
    public String getPackageId() {
      final AtomicReference<String> packageId = new AtomicReference<>();
      ApplicationManager.getApplication().invokeAndWait(() -> {
        AndroidFacet androidFacet = AndroidFacet.getInstance(myModule);
        if (androidFacet != null) {
          AndroidModel androidModel = androidFacet.getConfiguration().getModel();
          if (androidModel != null) {
            packageId.set(androidModel.getApplicationId());
          }
        }
      }, ModalityState.any());
      return packageId.get();
    }
  }
}