/*
 * Copyright 2019 Google LLC
 *
 * 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
 *
 *     https://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.cloud.buildartifacts.gradle.plugin;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.AccessToken;
import com.google.cloud.buildartifacts.auth.CredentialProvider;
import com.google.cloud.buildartifacts.auth.DefaultCredentialProvider;

import java.io.IOException;
import java.net.URI;

import org.gradle.api.artifacts.repositories.ArtifactRepository;
import org.gradle.api.artifacts.repositories.PasswordCredentials;
import org.gradle.api.credentials.Credentials;
import org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.ProjectConfigurationException;

public class BuildArtifactsGradlePlugin implements Plugin<Project> {

  static class BuildArtifactsPasswordCredentials implements PasswordCredentials {
    private String username;
    private String password;

    public BuildArtifactsPasswordCredentials(String username, String password) {
      this.username = username;
      this.password = password;
    }

    @Override
    public String getUsername() {
      return username;
    }

    @Override
    public String getPassword() {
      return password;
    }

    @Override
    public void setUsername(String username) {
      this.username = username;
    }

    @Override
    public void setPassword(String password) {
      this.password = password;
    }
  }

  private CredentialProvider credentialProvider = new DefaultCredentialProvider();

  @Override
  public void apply(Project project) {
    project.afterEvaluate(p -> {
      project.getRepositories().all(this::configureBuildArtifactsRepositories);
      final PublishingExtension publishingExtension = project.getExtensions().findByType(PublishingExtension.class);
      if (publishingExtension != null) {
        publishingExtension.getRepositories().all(this::configureBuildArtifactsRepositories);
      }
    });
  }

  public void configureBuildArtifactsRepositories(ArtifactRepository repo)
      throws ProjectConfigurationException
      {
        try {
          GoogleCredentials credentials = (GoogleCredentials)credentialProvider.getCredential();
          AccessToken accessToken = credentials.getAccessToken();
          String token = accessToken.getTokenValue();

          if (!(repo instanceof DefaultMavenArtifactRepository)) {
            return;
          }
          final DefaultMavenArtifactRepository cbaRepo = (DefaultMavenArtifactRepository) repo;
          final URI u = cbaRepo.getUrl(); 
          if (u != null && u.getScheme() != null && u.getScheme().equals("buildartifacts")) {
            cbaRepo.setUrl(new URI("https", u.getHost(), u.getPath(), u.getFragment()));
            BuildArtifactsPasswordCredentials crd = new BuildArtifactsPasswordCredentials("oauth2accesstoken", token);
            cbaRepo.setConfiguredCredentials((Credentials)crd);
          }
        } catch (Exception e) {
          System.out.println(e.toString());
          Throwable cause = e.getCause();
          throw (ProjectConfigurationException) cause;
        }
      }
}



@@ -921,16 +921,52 @@
 net.URI;
+%0Aimport java.net.URISyntaxException;
 %0A%0Aimport
@@ -1387,16 +1387,60 @@
 ception;
+%0Aimport org.gradle.api.UncheckedIOException;
 %0A%0Apublic
@@ -2798,251 +2798,39 @@
 tion
-%0A      %7B%0A        try %7B%0A          GoogleCredentials credentials = (GoogleCredentials)credentialProvider.getCredential();%0A          AccessToken accessToken = credentials.getAccessToken();%0A          String token = accessToken.getTokenValue();%0A%0A  
+, UncheckedIOException%0A      %7B%0A
     
@@ -2904,18 +2904,16 @@
     
-  
 return;%0A
     
@@ -2908,18 +2908,16 @@
 return;%0A
-  
         
@@ -2922,26 +2922,24 @@
   %7D%0A        
-  
 final Defaul
@@ -3012,18 +3012,16 @@
 ) repo;%0A
-  
         
@@ -3057,26 +3057,24 @@
 ); %0A        
-  
 if (u != nul
@@ -3142,24 +3142,39 @@
 facts%22)) %7B%0A 
+         try %7B%0A
            c
@@ -3164,32 +3164,33 @@
 ry %7B%0A           
+ 
 cbaRepo.setUrl(n
@@ -3246,24 +3246,503 @@
 agment()));%0A
+          %7D catch (URISyntaxException e) %7B%0A            throw new ProjectConfigurationException(String.format(%22Invalid repository URL %25s%22, u.toString()), e);%0A          %7D%0A%0A          if (cbaRepo.getConfiguredCredentials() == null) %7B%0A            try %7B%0A              GoogleCredentials credentials = (GoogleCredentials)credentialProvider.getCredential();%0A              AccessToken accessToken = credentials.getAccessToken();%0A              String token = accessToken.getTokenValue();%0A  
             
@@ -3848,16 +3848,18 @@
 token);%0A
+  
         
@@ -3918,24 +3918,16 @@
 d);%0A    
-      %7D%0A
         
@@ -3935,16 +3935,18 @@
  catch (
+IO
 Exceptio
@@ -3966,138 +3966,114 @@
     
-System.out.println(e.toString());%0A          Throwable cause = e.getCause();%0A          throw (ProjectConfigurationException) cause;
+    throw new UncheckedIOException(%22Failed to get access token from gcloud%22, e);%0A            %7D%0A          %7D
 %0A   
@@ -4090,9 +4090,8 @@
    %7D%0A%7D%0A%0A
-%0A

reorder the configure repo logic and add more explicit exceptions