import os
import logging

import mini_buildd.files
import mini_buildd.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:" + mini_buildd.call.Call([COMMAND,
                                                           "--begin-session",
                                                           "--chroot", self.chroot]).check().stdout.strip()
        LOG.info(f"{self}: Schroot session started ({self.chroot})")

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

        .. error:: **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).
        """
        mini_buildd.call.call_with_retry([COMMAND,
                                          "--end-session",
                                          "--chroot", self.session,
                                          ],
                                         retry_max_tries=10,
                                         retry_sleep=1)
        LOG.info(f"{self}: Schroot session closed ({self.chroot})")

    def call(self, call, user="root"):
        return mini_buildd.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 mini_buildd.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 unsecure 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 mini_buildd.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.info(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.info(f"{self}: Debconf value set: {key}={value}")
