# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import functools
import logging
import portage
from portage import os
from portage.dbapi._MergeProcess import MergeProcess
from portage.exception import UnsupportedAPIException
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
from _emerge.EbuildBuildDir import EbuildBuildDir
from _emerge.emergelog import emergelog
from _emerge.CompositeTask import CompositeTask
from _emerge.unmerge import _unmerge_display


class PackageUninstall(CompositeTask):
    """
    Uninstall a package asynchronously in a subprocess. When
    both parallel-install and ebuild-locks FEATURES are enabled,
    it is essential for the ebuild-locks code to execute in a
    subprocess, since the portage.locks module does not behave
    as desired if we try to lock the same file multiple times
    concurrently from the same process for ebuild-locks phases
    such as pkg_setup, pkg_prerm, and pkg_postrm.
    """

    __slots__ = (
        "world_atom",
        "ldpath_mtimes",
        "opts",
        "pkg",
        "settings",
        "_builddir_lock",
    )

    def _start(self):

        vardb = self.pkg.root_config.trees["vartree"].dbapi
        dbdir = vardb.getpath(self.pkg.cpv)
        if not os.path.exists(dbdir):
            # Apparently the package got uninstalled
            # already, so we can safely return early.
            self.returncode = os.EX_OK
            self._async_wait()
            return

        self.settings.setcpv(self.pkg)
        cat, pf = portage.catsplit(self.pkg.cpv)
        myebuildpath = os.path.join(dbdir, pf + ".ebuild")

        try:
            portage.doebuild_environment(
                myebuildpath, "prerm", settings=self.settings, db=vardb
            )
        except UnsupportedAPIException:
            # This is safe to ignore since this function is
            # guaranteed to set PORTAGE_BUILDDIR even though
            # it raises UnsupportedAPIException. The error
            # will be logged when it prevents the pkg_prerm
            # and pkg_postrm phases from executing.
            pass

        self._builddir_lock = EbuildBuildDir(
            scheduler=self.scheduler, settings=self.settings
        )
        self._start_task(
            AsyncTaskFuture(future=self._builddir_lock.async_lock()),
            self._start_unmerge,
        )

    def _start_unmerge(self, lock_task):
        self._assert_current(lock_task)
        if lock_task.cancelled:
            self._default_final_exit(lock_task)
            return

        lock_task.future.result()
        portage.prepare_build_dirs(settings=self.settings, cleanup=True)

        # Output only gets logged if it comes after prepare_build_dirs()
        # which initializes PORTAGE_LOG_FILE.
        retval, _ = _unmerge_display(
            self.pkg.root_config,
            self.opts,
            "unmerge",
            [self.pkg.cpv],
            clean_delay=0,
            writemsg_level=self._writemsg_level,
        )

        if retval != os.EX_OK:
            self._async_unlock_builddir(returncode=retval)
            return

        self._writemsg_level(">>> Unmerging %s...\n" % (self.pkg.cpv,), noiselevel=-1)
        self._emergelog("=== Unmerging... (%s)" % (self.pkg.cpv,))

        cat, pf = portage.catsplit(self.pkg.cpv)
        unmerge_task = MergeProcess(
            mycat=cat,
            mypkg=pf,
            settings=self.settings,
            treetype="vartree",
            vartree=self.pkg.root_config.trees["vartree"],
            scheduler=self.scheduler,
            background=self.background,
            mydbapi=self.pkg.root_config.trees["vartree"].dbapi,
            prev_mtimes=self.ldpath_mtimes,
            logfile=self.settings.get("PORTAGE_LOG_FILE"),
            unmerge=True,
        )

        self._start_task(unmerge_task, self._unmerge_exit)

    def _unmerge_exit(self, unmerge_task):
        if self._final_exit(unmerge_task) != os.EX_OK:
            self._emergelog(" !!! unmerge FAILURE: %s" % (self.pkg.cpv,))
        else:
            self._emergelog(" >>> unmerge success: %s" % (self.pkg.cpv,))
            self.world_atom(self.pkg)
        self._async_unlock_builddir(returncode=self.returncode)

    def _async_unlock_builddir(self, returncode=None):
        """
        Release the lock asynchronously, and if a returncode parameter
        is given then set self.returncode and notify exit listeners.
        """
        if returncode is not None:
            # The returncode will be set after unlock is complete.
            self.returncode = None
        self._start_task(
            AsyncTaskFuture(future=self._builddir_lock.async_unlock()),
            functools.partial(self._unlock_builddir_exit, returncode=returncode),
        )

    def _unlock_builddir_exit(self, unlock_task, returncode=None):
        self._assert_current(unlock_task)
        if unlock_task.cancelled and returncode is not None:
            self._default_final_exit(unlock_task)
            return

        # Normally, async_unlock should not raise an exception here.
        unlock_task.future.cancelled() or unlock_task.future.result()
        if returncode is not None:
            self.returncode = returncode
            self._async_wait()

    def _emergelog(self, msg):
        emergelog("notitles" not in self.settings.features, msg)

    def _writemsg_level(self, msg, level=0, noiselevel=0):

        log_path = self.settings.get("PORTAGE_LOG_FILE")
        background = self.background

        if log_path is None:
            if not (background and level < logging.WARNING):
                portage.util.writemsg_level(msg, level=level, noiselevel=noiselevel)
        else:
            self.scheduler.output(
                msg, log_path=log_path, level=level, noiselevel=noiselevel
            )
