#!/usr/bin/env python3
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
#
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Michael Terry

import os
import shutil
from datetime import datetime

from dogtail.predicate import GenericPredicate
from dogtail.rawinput import keyCombo
from gi.repository import GLib

from . import BaseTest, ResticMixin


class RestoreTest(BaseTest):
    __test__ = False

    def setUp(self):
        super().setUp()
        self.folder = self.get_config(
            "default", "folder", fallback="deja-dup-test", required=False
        )
        self.filename = self.srcdir + "/[t](e?s*)' t.\"txt"
        self.contents = datetime.now().isoformat()
        open(self.filename, "w").write(self.contents)

    def walk_backup(self, app):
        window = self.get_dialog(app)
        window.button("Back Up").click()

        self.enter_browser_password(app, "test-restore")

        self.wait_for_banner(app, "Pause")

    def fill_out_restore_dialog(self, dlg):
        pass  # for subclasses to fill out

    def walk_restore(self, app):
        shutil.rmtree(self.srcdir)

        window = self.get_dialog(app)
        self.fill_out_restore_dialog(window)
        window.button("Search").click()

        # Switched to restore pane. Enter password if using restic, which
        # unlike duplicity, does not keep unencrypted metadata locally cached.
        if self.restic:
            self.enter_browser_password(app, "test-restore")

        # Select most recent date
        self.wait_for(
            lambda: app.findChild(
                GenericPredicate(roleName="list item"),
                retry=False,
                requireResult=False,
            ),
            timeout=120,
        )
        app.child(roleName="list item").click()

        if self.restic:
            self.wait_for_file_manager()
            return

        # Now select all.
        search = app.child(roleName="toggle button", name="Search")
        self.wait_for(lambda: search.sensitive, timeout=300)
        keyCombo("<Control>a")

        # And start restore
        self.click_restore_button(app)
        window = self.get_dialog(app)
        window.button("Restore").click()  # to where

        self.enter_browser_password(app, "test-restore")

        self.wait_for_banner(app, "Stop", check_first=False)

        test_file = open(self.filename, "r")
        assert test_file.read(None) == self.contents

    def test_simple_cycle(self):
        app = self.cmd()

        app.childNamed("Create Your First Backup…").click()
        self.walk_backup(app)

        self.set_string("last-run", "")  # go back to welcome screen

        # Clear out backend settings
        self.reset_gsettings(self.get_string("backend"))

        app.childNamed("Restore From a Previous Backup…").click()
        self.walk_restore(app)


class LocalRestoreTest(RestoreTest):
    __test__ = True

    def setUp(self):
        super().setUp()
        self.set_string("backend", "local")
        self.set_string("folder", self.rootdir + "/dest", child="local")

    def fill_out_restore_dialog(self, dlg):
        assert self.get_string("backend") == "local"
        dlg.child(label="Folder").text = self.rootdir + "/dest"


class ResticLocalRestoreTest(ResticMixin, LocalRestoreTest):
    def setUp(self):
        super().setUp()
        self.set_string("folder", self.rootdir + "/dest-restic", child="local")

    def fill_out_restore_dialog(self, dlg):
        super().fill_out_restore_dialog(dlg)
        dlg.child(label="Folder").text = self.rootdir + "/dest-restic"


class GoogleRestoreTest(RestoreTest):
    __test__ = True

    def setUp(self):
        super().setUp()
        if not int(self.get_config("google", "enabled", fallback="0")):
            self.skipTest("Google not enabled")
        self.set_string("backend", "google")
        self.set_string("folder", self.folder, child="google")

    def fill_out_restore_dialog(self, dlg):
        assert self.get_string("backend") == "google"
        dlg.child(label="Folder").text = self.folder


class ResticGoogleRestoreTest(ResticMixin, GoogleRestoreTest):
    def setUp(self):
        super().setUp()
        self.set_string("folder", self.folder + "-restic", child="google")

    def fill_out_restore_dialog(self, dlg):
        super().fill_out_restore_dialog(dlg)
        dlg.child(label="Folder").text = self.folder + "-restic"


class MicrosoftRestoreTest(RestoreTest):
    __test__ = True

    def setUp(self):
        super().setUp()
        if not int(self.get_config("microsoft", "enabled", fallback="0")):
            self.skipTest("Microsoft not enabled")
        self.set_string("backend", "microsoft")
        self.set_string("folder", self.folder, child="microsoft")

    def fill_out_restore_dialog(self, dlg):
        assert self.get_string("backend") == "microsoft"
        dlg.child(label="Folder").text = self.folder


class ResticMicrosoftRestoreTest(ResticMixin, MicrosoftRestoreTest):
    def setUp(self):
        super().setUp()
        self.set_string("folder", self.folder + "-restic", child="microsoft")

    def fill_out_restore_dialog(self, dlg):
        super().fill_out_restore_dialog(dlg)
        dlg.child(label="Folder").text = self.folder + "-restic"


class RemoteRestoreTest(RestoreTest):
    __test__ = True

    def setUp(self):
        super().setUp()
        uri = self.get_config("remote", "uri")
        self.set_string("backend", "remote")
        self.set_string("uri", uri, child="remote")
        self.set_string("folder", self.folder, child="remote")

    def fill_out_restore_dialog(self, dlg):
        assert self.get_string("backend") == "remote"
        uri = self.get_config("remote", "uri")
        dlg.child(label="Server Address").text = uri
        dlg.child(label="Folder").text = self.folder


class ResticRemoteRestoreTest(ResticMixin, RemoteRestoreTest):
    def setUp(self):
        super().setUp()
        self.set_string("folder", self.folder + "-restic", child="remote")

    def fill_out_restore_dialog(self, dlg):
        super().fill_out_restore_dialog(dlg)
        dlg.child(label="Folder").text = self.folder + "-restic"


class RcloneRestoreTest(RestoreTest):
    __test__ = True

    def setUp(self):
        super().setUp()
        self.set_string("backend", "rclone")
        self.set_string("remote", ":local", child="rclone")
        self.set_string("folder", self.rootdir + "/dest", child="rclone")

    def fill_out_restore_dialog(self, dlg):
        assert self.get_string("backend") == "rclone"
        dlg.child(label="Remote").text = ":local"
        dlg.child(label="Folder").text = self.rootdir + "/dest"


class ResticRcloneRestoreTest(ResticMixin, RcloneRestoreTest):
    def setUp(self):
        super().setUp()
        self.set_string("folder", self.rootdir + "/dest-restic", child="rclone")

    def fill_out_restore_dialog(self, dlg):
        super().fill_out_restore_dialog(dlg)
        dlg.child(label="Folder").text = self.rootdir + "/dest-restic"

    def test_bogus_remote(self):
        self.set_string("remote", "bogus", child="rclone")

        app = self.cmd()
        app.childNamed("Create Your First Backup…").click()
        window = self.get_dialog(app)
        window.button("Back Up").click()

        app.button("Details").click()
        app.child(
            roleName="label",
            name="Rclone remote 'bogus' needs to be configured in Rclone first.",
        )
