/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*-
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 * SPDX-FileCopyrightText: Michael Terry
 */

/**
 * This backend is for the consumer-focused storage offering by Google.
 * At the time of this writing, it is called Google Drive.
 *
 * See the following doc for more info on how we authorize ourselves:
 * https://developers.google.com/identity/protocols/OAuth2InstalledApp
 */

using GLib;

namespace DejaDup {

public const string GOOGLE_ROOT = "Google";
public const string GOOGLE_FOLDER_KEY = "folder";

public const string GOOGLE_SERVER = "google.com";

public class BackendGoogle : BackendOAuth
{
  public BackendGoogle(Settings? settings) {
    Object(kind: Kind.GOOGLE,
           settings: (settings != null ? settings : get_settings(GOOGLE_ROOT)));
  }

  construct {
    // OAuth class properties
    brand_name = "Google";
    client_id = Config.GOOGLE_CLIENT_ID;
    auth_url = "https://accounts.google.com/o/oauth2/v2/auth";
    token_url = "https://www.googleapis.com/oauth2/v4/token";
    scope = "https://www.googleapis.com/auth/drive.file";
  }

  public override string get_redirect_uri()
  {
    var id_parts = client_id.split(".");
    string[] reversed = {};
    for (int i = id_parts.length - 1; i >= 0; i--) {
      reversed += id_parts[i];
    }
    // Exact path does not matter and is optional. But it seems wise to use some
    // path and this one seems reasonable (and is the example in their oauth docs).
    return "%s:/oauth2redirect".printf(string.joinv(".", reversed));
  }

  public override bool needs_dependencies() {
    return Environment.find_program_in_path(Rclone.rclone_command()) == null;
  }

  public override string[] get_dependencies() {
    return Config.RCLONE_PACKAGES.split(",");
  }

  public override Icon? get_icon() {
    return new ThemedIcon("deja-dup-google-drive");
  }

  public override async bool is_ready(out string reason, out string message) {
    reason = "google-reachable";
    message = _("Backup will begin when a network connection becomes available.");
    return yield Network.get().can_reach("https://%s/".printf(GOOGLE_SERVER));
  }

  public string get_folder() {
    return get_folder_key(settings, GOOGLE_FOLDER_KEY);
  }

  public override string get_location_pretty()
  {
    var folder = get_folder();
    if (folder == "")
      return _("Google Drive");
    else
      // Translators: %s is a folder.
      return _("%s on Google Drive").printf(folder);
  }

  protected override string get_unique_location()
  {
    return "google:" + get_folder();
  }

  public override async void get_space(out uint64 free, out uint64 total)
  {
    yield Rclone.get_space(this, out free, out total);
  }

  public override async List<string> peek_at_files()
  {
    return yield Rclone.list_files(this, 20);
  }

  public string fill_envp(ref List<string> envp)
  {
    // Setting the config path to empty prevents Rclone from trying to read
    // from its default config file (which we don't need, but might be
    // encrypted and thus cause an error).
    envp.append("RCLONE_CONFIG=");

    envp.append("RCLONE_DRIVE_CLIENT_ID=" + client_id);
    envp.append("RCLONE_DRIVE_TOKEN=" + full_token);
    envp.append("RCLONE_DRIVE_SCOPE=drive.file");
    envp.append("RCLONE_DRIVE_USE_TRASH=false");
    return ":drive:" + get_folder();
  }
}

} // end namespace

