# Copyright 2023 Northern.tech AS
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

import time

import pytest

from .. import conftest
from ..common_setup import enterprise_one_rofs_commercial_client_bootstrapped
from .common_update import update_image
from testutils.common import ApiClient
import testutils.api.deployments as deployments

from ..MenderAPI import (
    image,
    DeviceAuthV2,
    Deployments,
    get_container_manager,
)
from .mendertesting import MenderTesting


class BaseTestAutogenerateDelta(MenderTesting):
    def do_test_update_with_autogenerated_delta(
        self,
        env,
        valid_image_rofs_commercial_with_mender_conf,
    ):
        """Upgrade a device with auto-generated delta artifact"""

        mender_device = env.device
        devauth = DeviceAuthV2(env.auth)
        deploy = Deployments(env.auth, devauth)

        mender_conf = mender_device.run("cat /etc/mender/mender.conf")
        valid_image_rofs = valid_image_rofs_commercial_with_mender_conf(mender_conf)
        if valid_image_rofs is None:
            pytest.skip(
                "Thud branch and older from Yocto does not have R/O rootfs support"
            )

        # Configure delta auto-generation
        dc = ApiClient(
            deployments.URL_INTERNAL,
            host=get_container_manager().get_ip_of_service("mender-deployments")[0]
            + ":8080",
            schema="http://",
        )

        r = dc.call(
            "PUT",
            deployments.URL_INTERNAL_CONFIG,
            body={
                "delta": {
                    "enabled": True,
                    "binary_delta_limits": {
                        "jobs_in_parallel": {"max": 2},
                        "queue_length": {"max": 4},
                    },
                    "binary_delta": {"timeout": 3600},
                }
            },
            path_params={"tenant_id": env.tenant["id"]},
        )

        assert r.ok, "Failed to set the delta configuration"

        def make_artifact(artifact_file, artifact_id):
            return image.make_rootfs_artifact(
                valid_image_rofs,
                conftest.machine_name,
                artifact_id,
                artifact_file,
                provides={
                    "rootfs-image.update-module.mender-binary-delta.mender_update_module": "mender-binary-delta",
                    "rootfs-image.update-module.mender-binary-delta.version": "mender-image-master",
                },
            )

        host_ip = env.get_virtual_network_host_ip()
        update_image(
            mender_device,
            host_ip,
            make_artifact=make_artifact,
            devauth=devauth,
            deploy=deploy,
        )

        def make_artifact2(artifact_file, artifact_id):
            return image.make_rootfs_artifact(
                valid_image_rofs,
                conftest.machine_name,
                artifact_id,
                artifact_file,
                provides={
                    "rootfs-image.update-module.mender-binary-delta.mender_update_module": "mender-binary-delta2",
                    "rootfs-image.update-module.mender-binary-delta.version": "mender-image-master2",
                },
            )

        # check if client is applying delta
        def deployment_triggered_callback():
            isDelta = False
            # wait a minute
            i = 60
            while i > 0:
                output = mender_device.run(
                    "grep 'xdelta3' /data/mender/deployments.*.log",
                    warn=True,
                )
                if output != "":
                    isDelta = True
                    break
                i = i - 1
                time.sleep(1)

            assert isDelta, "No sign of applying delta in the deployment logs"

        update_image(
            mender_device,
            host_ip,
            make_artifact=make_artifact2,
            devauth=devauth,
            deploy=deploy,
            deployment_triggered_callback=deployment_triggered_callback,
            autogenerate_delta=True,
        )


class TestAutogenerateDeltaEnterprise(BaseTestAutogenerateDelta):
    @MenderTesting.fast
    def test_update_with_autogenerated_delta(
        self,
        enterprise_one_rofs_commercial_client_bootstrapped,
        valid_image_rofs_commercial_with_mender_conf,
    ):
        self.do_test_update_with_autogenerated_delta(
            enterprise_one_rofs_commercial_client_bootstrapped,
            valid_image_rofs_commercial_with_mender_conf,
        )
