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

using GLib;

[GtkTemplate (ui = "/org/gnome/DejaDup/SnapshotsPage.ui")]
public class SnapshotsPage : Adw.NavigationPage
{
  public signal void browse(DejaDup.Operation.State state, string tag);

  public void scan(DejaDup.Backend? backend = null)
  {
    saved_state = null;

    try {
      var op = OperationLauncher.get_instance().create_list_snapshots(backend);
      operation.set(op);

      op.collection_dates.connect(handle_collection_dates);
      status_page.connect_to_operation(op);

      op.start.begin();
    } catch (Error e) {
      status_page.set_error_state(e.message);
    }

    cancel_mount.reset();
    stack.visible_child_name = "operation";
  }

  [GtkChild]
  unowned Gtk.Stack stack;
  [GtkChild]
  unowned Gtk.ListBox list_view;
  [GtkChild]
  unowned OperationStatusPage status_page;
  [GtkChild]
  unowned Gtk.ProgressBar progress;

  WeakRef operation;
  DejaDup.Operation.State saved_state;
  Cancellable cancel_mount;

  construct {
    var op_watcher = DejaDup.OperationWatcher.get_instance();
    op_watcher.bind_property(
      "active", list_view, "sensitive",
      BindingFlags.SYNC_CREATE | BindingFlags.INVERT_BOOLEAN
    );

    cancel_mount = new Cancellable();
  }

  [GtkCallback]
  void handle_hiding()
  {
    cancel_mount.cancel();
    var op = operation.get() as DejaDup.Operation;
    if (op != null)
      op.stop();
    operation.set(null);
  }

  void handle_collection_dates(DejaDup.Operation op, List<DejaDup.SnapshotInfo> dates)
  {
    saved_state = op.get_state();

    if (dates.length() == 0) {
      stack.visible_child_name = "no-snapshots";
      return;
    }

    dates.sort((a, b) => {return a.time.compare(b.time);});

    list_view.remove_all();
    dates.foreach((info) => {
      info.time = info.time.to_local();

      var user_str = info.time.format("%c");
      list_view.prepend(make_row(user_str, info.external_description, info.tag));
    });

    stack.visible_child_name = "list";
  }

  Gtk.Widget make_row(string title, string? desc, string tag)
  {
    var row = new Adw.ActionRow();
    row.activatable = true;
    row.title = title;
    row.subtitle = desc;
    var icon_name = "go-next-symbolic";
    if (saved_state.tool.supports_mount())
      icon_name = "external-link-symbolic";
    row.add_suffix(new Gtk.Image.from_icon_name(icon_name));
    row.set_data_full("tag", tag.dup(), free);
    return row;
  }

  async void mount(string tag)
  {
    list_view.sensitive = false;

    var pulse_id = Timeout.add(250, () => {
      progress.visible = true;
      progress.pulse();
      return Source.CONTINUE;
    });

    string error_msg = null;
    try {
      var dir = yield DejaDup.MountManager.get_instance().mount(saved_state, tag, cancel_mount);
      if (dir != null) {
        var launcher = new Gtk.FileLauncher(File.new_for_path(dir));
        yield launcher.launch(this.root as Gtk.Window, cancel_mount);
      }
    } catch (IOError.CANCELLED e) {
      // ignore
    } catch (DejaDup.MountError e) {
      error_msg = e.message;
    } catch (Error e) {
      error_msg = e.message + "\n\n" + _("Try closing any open file manager windows and trying again.");
    }

    if (error_msg != null) {
      yield DejaDup.run_error_dialog(this, _("Failed to Open Backup"), error_msg);
    }

    Source.remove(pulse_id);
    progress.visible = false;
    list_view.sensitive = true;
  }

  [GtkCallback]
  void row_activated(Gtk.ListBoxRow row)
  {
    var tag = row.get_data<string>("tag");
    if (saved_state.tool.supports_mount())
      mount.begin(tag);
    else
      browse(saved_state, tag);
  }
}
