import os
import logging

from mini_buildd import util, call

LOG = logging.getLogger(__name__)

COMMAND = "/usr/bin/schroot"


class Session():
    def __init__(self, name, namespace="chroot"):
        self.chroot = f"{namespace}:{name}"
        self.session = "session:" + call.Call([COMMAND,
                                               "--begin-session",
                                               "--chroot", self.chroot]).check().stdout.strip()
        LOG.debug(f"{self}: Schroot session started ({self.chroot})")

    def close(self):
        """
        Close session (including retries on failure)

        .. attention:: **stale schroot sessions**: 'target is busy' on session close (stale schroot sessions)

           Occasionally, a schroot session can't be closed
           properly, leaving stale sessions around. Presumably,
           external programs (like 'desktop mount scanners') can cause
           this.

           This internal close does try hard to avoid this -- however,
           if disaster strikes anyway, ``mini-buildd-schroot-cleanup``
           may help to remove these stale sessions manually (i.e., as
           ``mini-buildd`` user from the shell).
        """
        call.call_with_retry([COMMAND,
                              "--end-session",
                              "--chroot", self.session,
                              ],
                             retry_max_tries=10,
                             retry_sleep=1)
        LOG.debug(f"{self}: Schroot session closed ({self.chroot})")

    def call(self, _call, user="root"):
        return call.Call([COMMAND,
                          "--run-session",
                          "--chroot", self.session,
                          "--user", user] + _call)

    def run(self, _call, user="root"):
        return self.call(_call, user=user).check().stdout

    def info(self):
        return call.Call([COMMAND,
                          "--info",
                          "--chroot", self.session]).check().stdout

    def __str__(self):
        return f"{self.session}"

    def check_sudo_workaround(self):
        """
        .. attention:: **compat** (``mini-buildd <= 1.0.4``): Fail for very old and possibly insecure chroots

          mini-buildd <= 1.0.4 created chroots with a "sudo workaround" for bug
          https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=607228.

          Such chroots must be recreated, and no longer used (for security reasons).
        """
        has_sudo_workaround = self.call(["--directory", "/", "--", "grep", f"^{os.getenv('USER')}", "/etc/sudoers"])
        if has_sudo_workaround.success():
            raise util.HTTPBadRequest(f"{self}: Has sudo workaround (created with versions <= 1.0.4): Please run 'Remove' + 'PCA' on this chroot to re-create!")

    def update_file(self, file_path, content):
        """Write content to file"""
        self.run(["--", "/bin/sh", "-c", f"echo '{content}' >{file_path}"])
        LOG.debug(f"{self}: Updated file '{file_path}': {content}")

    def set_debconf(self, key, value):
        """Set arbitrary debconf value"""
        self.run(["--", "/bin/sh", "-c", f"export DEBIAN_FRONTEND=noninteractive && echo 'set {key} {value}' | debconf-communicate"])
        LOG.debug(f"{self}: Debconf value set: {key}={value}")
