#!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/common/pywrap", sys.argv)

# This file is part of Cockpit.
#
# Copyright (C) 2021 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

import machineslib
import testlib


@testlib.nondestructive
class TestMachinesFilesystems(machineslib.VirtualMachinesCase):
    def testBasicSystemConnection(self):
        self._testBasic()

    def testBasicSessionConnection(self):
        self._testBasic("session")

    def _testBasic(self, connection="system"):
        b = self.browser
        m = self.machine

        m.execute("mkdir -p /tmp/dir1 /tmp/dir2")

        self.login_and_go("/machines")
        self.waitPageInit()
        self.createVm("subVmTest1", running=False, connection=connection)
        self.goToVmPage("subVmTest1", connectionName=connection)
        # wait until page initialized
        b.wait_visible("#vm-subVmTest1-hostdevs")

        if connection == "session":
            b.wait_not_present("#vm-subVmTest1-filesystems-add")
            return

        # Form validation
        b.click("#vm-subVmTest1-filesystems-add")

        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_visible("#vm-subVmTest1-filesystems-modal-source-helper")
        b.wait_visible("#vm-subVmTest1-filesystems-modal-mountTag-helper")

        b.set_input_text("#vm-subVmTest1-filesystems-modal-mountTag", "test")
        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_text("#vm-subVmTest1-filesystems-modal-source-helper", "Source must not be empty")
        b.wait_not_present("#vm-subVmTest1-filesystems-modal-mountTag-helper")

        b.set_input_text("#vm-subVmTest1-filesystems-modal-mountTag", "")
        b.set_file_autocomplete_val("#vm-subVmTest1-filesystems-modal-source-group", "/tmp/")
        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_not_present("#vm-subVmTest1-filesystems-modal-source-helper")
        b.wait_text("#vm-subVmTest1-filesystems-modal-mountTag-helper", "Mount tag must not be empty")

        b.click("#vm-subVmTest1-filesystems-modal-cancel")

        # Add a new shared filesystem
        b.click("#vm-subVmTest1-filesystems-add")
        b.set_file_autocomplete_val("#vm-subVmTest1-filesystems-modal-source-group", "/tmp/dir1/")
        b.set_input_text("#vm-subVmTest1-filesystems-modal-mountTag", "dir1")
        b.click(".pf-v5-c-expandable-section__toggle")
        b.wait_visible("#vm-subVmTest1-filesystems-modal-xattr:not(:checked)")
        # Check "Extended attributes" text
        b.wait_text('#vm-subVmTest1-filesystems-modal-xattr + label',
                    "Use extended attributes on files and directories")
        b.set_checked("#vm-subVmTest1-filesystems-modal-xattr", True)

        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_not_present("#vm-subVmTest1-filesystems-modal-add")
        b.wait_in_text("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir1/-dir1'] td[data-label='Source path']",
                       "/tmp/dir1/")
        b.wait_in_text("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir1/-dir1'] td[data-label='Mount tag']",
                       "dir1")

        domain_xml = "virsh -c qemu:///system dumpxml subVmTest1"
        xmllint_element = f"{domain_xml} | xmllint --xpath 'string(//domain/{{prop}})' -"

        self.assertEqual('/tmp/dir1/',
                         m.execute(xmllint_element.format(prop='devices/filesystem/source/@dir')).strip())
        self.assertEqual('dir1', m.execute(xmllint_element.format(prop='devices/filesystem/target/@dir')).strip())
        self.assertEqual('on', m.execute(xmllint_element.format(prop='devices/filesystem/binary/@xattr')).strip())
        self.assertEqual('shared', m.execute(xmllint_element.format(prop='memoryBacking/access/@mode')).strip())

        # Add a new shared filesystem - now the memoryBacking is configured and hidden from the dialog
        b.click("#vm-subVmTest1-filesystems-add")
        b.set_file_autocomplete_val("#vm-subVmTest1-filesystems-modal-source-group", "/tmp/dir2/")
        b.set_input_text("#vm-subVmTest1-filesystems-modal-mountTag", "dir2")
        b.click(".pf-v5-c-expandable-section__toggle")
        b.set_checked("#vm-subVmTest1-filesystems-modal-xattr", False)

        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_not_present("#vm-subVmTest1-filesystems-modal-add")
        b.wait_in_text("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir2/-dir2'] td[data-label='Source path']",
                       "/tmp/dir2/")
        b.wait_in_text("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir2/-dir2'] td[data-label='Mount tag']",
                       "dir2")

        self.assertEqual('/tmp/dir2/',
                         m.execute(xmllint_element.format(prop='devices/filesystem[2]/source/@dir')).strip())
        self.assertEqual('dir2', m.execute(xmllint_element.format(prop='devices/filesystem[2]/target/@dir')).strip())
        self.assertEqual('', m.execute(xmllint_element.format(prop='devices/filesystem[2]/binary/@xattr')).strip())

        # Try to add a new shared filesystem with the same mount tag
        b.click("#vm-subVmTest1-filesystems-add")
        b.set_file_autocomplete_val("#vm-subVmTest1-filesystems-modal-source-group", "/tmp/dir1/")
        b.set_input_text("#vm-subVmTest1-filesystems-modal-mountTag", "dir1")
        b.click("#vm-subVmTest1-filesystems-modal-add")
        b.wait_in_text(".pf-v5-c-alert", "Failed to add shared directory")
        b.wait_in_text(".pf-v5-c-alert", "filesystem target 'dir1' specified twice")
        b.click("#vm-subVmTest1-filesystems-modal-cancel")

        # Try to add a new shared filesystem with non existing source directory
        b.click("#vm-subVmTest1-filesystems-add")
        b.set_input_text("#vm-subVmTest1-filesystems-modal-source-group input", "dir3")
        b.wait_in_text("#vm-subVmTest1-filesystems-modal-source-group ul", "No such file or directory")
        b.click("#vm-subVmTest1-filesystems-modal-source button[aria-label='Clear input value']")
        b.click("#vm-subVmTest1-filesystems-modal-source button[aria-label='Typeahead menu toggle']")
        b.blur("#vm-subVmTest1-filesystems-modal-source-group input")
        b.wait_not_present("#vm-subVmTest1-filesystems-modal-source  .pf-v5-c-menu")
        b.click("#vm-subVmTest1-filesystems-modal-cancel")
        b.wait_not_present(".pf-v5-c-modal-box__body ")

        # Start VM and ensure that adding filesystem is disabled
        b.click("#vm-subVmTest1-system-run")
        b.wait_visible("#vm-subVmTest1-filesystems-add[aria-disabled=true]")

    def testDelete(self):
        b = self.browser
        m = self.machine

        m.execute("mkdir -p /tmp/dir1")

        self.createVm("subVmTest1", running=False)
        self.login_and_go("/machines")
        self.waitPageInit()
        self.goToVmPage("subVmTest1")

        m.execute("virt-xml subVmTest1 --add-device --filesystem source=/tmp/dir1/,target=dir1")
        b.wait_visible("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir1/-dir1']")
        b.click("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir1/-dir1'] button:contains(Remove)")
        b.wait_in_text(".pf-v5-c-modal-box__body .pf-v5-c-description-list", "removed from subVmTest1")
        b.wait_in_text("#delete-resource-modal-source-path", "/tmp/dir1/")
        b.wait_in_text("#delete-resource-modal-mount-tag", "dir1")

        b.click("#delete-resource-modal button:contains(Remove)")
        b.wait_not_present("tr[data-row-id='vm-subVmTest1-filesystem-/tmp/dir1/-dir1']")


if __name__ == '__main__':
    testlib.test_main()
