#!/usr/bin/env python3
# This file is part of Xpra.
# Copyright (C) 2016 Antoine Martin <antoine@xpra.org>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import time
import socket
import unittest

from xpra.util.objects import typedict
from xpra.os_util import OSX, POSIX
from xpra.util.io import pollwait, which
from xpra.codecs.image import ImageWrapper
from unit.server_test_util import ServerTestUtil


class ShadowServerTest(ServerTestUtil):

    def start_shadow_server(self, *args):
        display = self.find_free_display()
        xvfb = self.start_Xvfb(display)
        assert display in self.find_X11_displays()
        #start server using this display:
        server = self.check_server("shadow", display, *args)
        return display, xvfb, server

    def stop_shadow_server(self, xvfb, server):
        self.check_stop_server(server, "stop", xvfb.display)
        time.sleep(1)
        assert pollwait(xvfb, 2) is None, "the Xvfb should not have been killed by xpra shutting down!"
        xvfb.terminate()

    def test_shadow_start_stop(self):
        _, xvfb, server = self.start_shadow_server()
        self.stop_shadow_server(xvfb, server)

    def test_dbus_interface(self):
        if not POSIX or OSX:
            return
        dbus_send = which("dbus-send")
        if not dbus_send:
            print("Warning: dbus test skipped, 'dbus-send' not found")
            return
        display, xvfb, server = self.start_shadow_server("-d", "dbus")
        info = self.get_server_info(xvfb.display)
        assert info
        tinfo = typedict(info)
        idisplay = tinfo.strget("server.display")
        assert idisplay==display, "expected display '%s' in info, but got '%s'" % (display, idisplay)
        try:
            import dbus
            assert dbus
        except ImportError:
            print("WARNING: python-dbus not found, the dbus interface cannot be tested")
        else:
            dstr = display.lstrip(":")
            new_delay = 2
            cmd = [
                dbus_send,
                "--session",
                "--type=method_call",
                f"--dest=org.xpra.Server{dstr}",
                "/org/xpra/Server",
                "org.xpra.Server.SetRefreshDelay",
                f"int32:{new_delay}",
            ]
            env = self.get_run_env()
            env["DISPLAY"] = display
            self.run_command(cmd, env=env).wait(20)
            time.sleep(1)
            #check that the value has changed:
            info = self.get_server_info(display)
            assert info
            tinfo = typedict(info)
            assert tinfo.strget("server.display")==display
            rd = tinfo.intget("refresh-delay", 0)
            assert rd==new_delay, f"expected refresh-delay={new_delay}, got {rd}"
        self.stop_shadow_server(xvfb, server)

    def test_root_window_model(self):
        from xpra.server.shadow.root_window_model import RootWindowModel
        W = 640
        H = 480

        class FakeDisplay:
            def get_name(self):
                return "fake-display"

        class FakeScreen:
            def get_display(self):
                return FakeDisplay()

        class FakeRootWindow:
            def get_screen(self):
                return FakeScreen()

            def get_geometry(self):
                return (0, 0, W, H)

        class FakeCapture:
            def take_screenshot(self):
                return self.get_image(0, 0, W, H)

            def get_image(self, x, y, w, h):
                pixels = "0"*w*4*h
                return ImageWrapper(x, y, w, h, pixels, "BGRA", 32, w*4, 4, ImageWrapper.PACKED, True, None)

            def get_info(self):
                return {"type" : "fake"}

        window = FakeRootWindow()
        rwm = RootWindowModel(window, FakeCapture(), geometry=window.get_geometry()[:4])
        assert repr(rwm)
        assert rwm.get_info()
        rwm.get_default_window_icon(32)
        for prop in ("title", "class-instance", "size-constraints", "icons"):
            rwm.get_property(prop)
        for prop, value in {
            "client-machine"    : socket.gethostname(),
            "window-type"        : ["NORMAL"],
            "fullscreen"        : False,
            "shadow"            : True,
            "depth"                : 24,
            "scaling"            : None,
            "opacity"            : None,
            "content-type"        : "desktop",
        }.items():
            assert rwm.get_property(prop)==value
        rwm.suspend()
        rwm.unmanage(True)
        assert rwm.take_screenshot()
        assert rwm.get_image(10, 10, 20, 20)
        rwm.geometry = (10, 10, W, H)
        img = rwm.get_image(10, 10, 20, 20)
        assert img.get_target_x()==10
        assert img.get_target_y()==10


def main():
    if POSIX and not OSX:
        unittest.main()


if __name__ == '__main__':
    main()
