// Copyright (C) 2018 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.googlesource.gerrit.plugins.replication;

import static com.googlesource.gerrit.plugins.replication.GerritSshApi.GERRIT_ADMIN_PROTOCOL_PREFIX;
import static com.googlesource.gerrit.plugins.replication.ReplicationQueue.repLog;

import com.google.common.base.Charsets;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicHeader;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;

public class GerritRestApi implements AdminApi {

  public interface Factory {
    GerritRestApi create(URIish uri);
  }

  private final CredentialsFactory credentials;
  private final CloseableHttpClient httpClient;
  private final RemoteConfig remoteConfig;
  private final URIish uri;

  @Inject
  GerritRestApi(
      CredentialsFactory credentials,
      CloseableHttpClient httpClient,
      RemoteConfig remoteConfig,
      @Assisted URIish uri) {
    this.credentials = credentials;
    this.httpClient = httpClient;
    this.remoteConfig = remoteConfig;
    this.uri = uri;
  }

  @Override
  public boolean createProject(Project.NameKey project, String head) {
    repLog.info("Creating project {} on {}", project, uri);
    String url = String.format("%s/a/projects/%s", toHttpUri(uri), Url.encode(project.get()));
    try {
      return httpClient
          .execute(new HttpPut(url), new HttpResponseHandler(), getContext())
          .isSuccessful();
    } catch (IOException e) {
      repLog.error("Couldn't perform project creation on {}", uri, e);
      return false;
    }
  }

  @Override
  public boolean deleteProject(Project.NameKey project) {
    repLog.info("Deleting project {} on {}", project, uri);
    String url = String.format("%s/a/projects/%s", toHttpUri(uri), Url.encode(project.get()));
    try {
      httpClient.execute(new HttpDelete(url), new HttpResponseHandler(), getContext());
      return true;
    } catch (IOException e) {
      repLog.error("Couldn't perform project deletion on {}", uri, e);
    }
    return false;
  }

  @Override
  public boolean updateHead(Project.NameKey project, String newHead) {
    repLog.info("Updating head of {} on {}", project, uri);
    String url = String.format("%s/a/projects/%s/HEAD", toHttpUri(uri), Url.encode(project.get()));
    try {
      HttpPut req = new HttpPut(url);
      req.setEntity(
          new StringEntity(String.format("{\"ref\": \"%s\"}", newHead), Charsets.UTF_8.name()));
      req.addHeader(new BasicHeader("Content-Type", "application/json"));
      httpClient.execute(req, new HttpResponseHandler(), getContext());
      return true;
    } catch (IOException e) {
      repLog.error("Couldn't perform update head on {}", uri, e);
    }
    return false;
  }

  private HttpClientContext getContext() {
    HttpClientContext ctx = HttpClientContext.create();
    ctx.setCredentialsProvider(adapt(credentials.create(remoteConfig.getName())));
    return ctx;
  }

  private CredentialsProvider adapt(org.eclipse.jgit.transport.CredentialsProvider cp) {
    CredentialItem.Username user = new CredentialItem.Username();
    CredentialItem.Password pass = new CredentialItem.Password();
    if (cp.supports(user, pass) && cp.get(uri, user, pass)) {
      CredentialsProvider adapted = new BasicCredentialsProvider();
      adapted.setCredentials(
          AuthScope.ANY,
          new UsernamePasswordCredentials(user.getValue(), new String(pass.getValue())));
      return adapted;
    }
    return null;
  }

  private static String toHttpUri(URIish uri) {
    String u = uri.toString();
    if (u.startsWith(GERRIT_ADMIN_PROTOCOL_PREFIX)) {
      u = u.substring(GERRIT_ADMIN_PROTOCOL_PREFIX.length());
    }
    if (u.endsWith("/")) {
      return u.substring(0, u.length() - 1);
    }
    return u;
  }
}

@@ -844,48 +844,63 @@
 og;%0A
-%0A
 import 
-com.google.common.base.Charsets;
+static java.nio.charset.StandardCharsets.UTF_8;%0A
 %0Aimp
@@ -3635,27 +3635,16 @@
 tEntity(
-%0A          
 new Stri
@@ -3697,25 +3697,16 @@
 wHead), 
-Charsets.
 UTF_8.na

Use UTF_8 from StandardCharsets instead of Guava