#!/usr/bin/env python3

import os

from setuptools import setup, Command, find_packages
from setuptools import Distribution
from setuptools.command.install import install


class CleanCommand(Command):
    user_options = []

    def initialize_options(self):
        # pylint: disable=attribute-defined-outside-init
        self.cwd = None

    def finalize_options(self):
        # pylint: disable=attribute-defined-outside-init
        self.cwd = os.getcwd()

    def run(self):
        assert os.getcwd() == self.cwd, "Must be in package root: %s" % self.cwd
        os.system("rm -rf ./build ./dist ./*.pyc ./*.egg-info")


# The following classes (_ScriptDirSpy, _SomeDir, ScriptDir, PlatLib, PureLib )
# allow to get some directories used by setuptools.
#
# The root reason for introduction `scriptdir` command was the error in
# setuptools, which caused wrong shebang in script files
# (see https://github.com/pypa/setuptools/issues/188 and
# https://bugzilla.redhat.com/1353934). As a workaround the shebang was
# corrected in pcs Makefile, however hardcoded path didn't work on some systems,
# so there was a need to get a reliable path to a script (or bin) directory.
#
# Alternative approach would be correct shebang here in `setup.py`. However, it
# would mean to deal with possible user options (like --root, --prefix,
# --install-lib etc. - or its combinations) consistently with setuptools (and it
# can be patched in some OS).
#
# Later it turn out that it is also necessary to obtain purelib/platlib in
# Makefile.
class _ScriptDirSpy(install):
    """
    Fake install. Its task is to make the some paths accessible to a caller.
    """

    def run(self):
        self.distribution.install_scripts = self.install_scripts
        self.distribution.install_purelib = self.install_purelib
        self.distribution.install_platlib = self.install_platlib


class _SomeDir(Command):
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        """
        Print desired path (according to subclass) to stdout.

        Unfortunately, setuptools automatically prints "running scriptdir" on
        stdout. So, for example, the output will look like this (for example):
        running scriptdir
        /usr/local/bin

        The shell command `tail` can be used to get only the relevant line:
        `python setup.py scriptdir | tail --lines=1`

        """

        # pylint: disable=no-self-use
        # Create fake install to get a setuptools script directory path.
        dist = Distribution({"cmdclass": {"install": _ScriptDirSpy}})
        dist.dry_run = True
        dist.parse_config_files()
        command = dist.get_command_obj("install")
        command.ensure_finalized()
        command.run()
        print(self.get_dir_from_distribution(dist))


class ScriptDir(_SomeDir):
    def get_dir_from_distribution(self, dist):
        return dist.install_scripts


class PlatLib(_SomeDir):
    def get_dir_from_distribution(self, dist):
        return dist.install_platlib


class PureLib(_SomeDir):
    def get_dir_from_distribution(self, dist):
        return dist.install_purelib


setup(
    name="pcs",
    version="0.10.8",
    description="Pacemaker Configuration System",
    author="Chris Feist",
    author_email="cfeist@redhat.com",
    url="https://github.com/ClusterLabs/pcs",
    packages=find_packages(exclude=["pcs_test", "pcs_test.*"]),
    package_data={
        "pcs": [
            "bash_completion",
            "pcs.8",
            "pcs",
        ]
    },
    zip_safe=False,
    entry_points={
        "console_scripts": [
            "pcs = pcs.entry_points.cli:main",
            "pcsd = pcs.entry_points.daemon:main",
            "pcs_snmp_agent = pcs.entry_points.snmp_agent:main",
            "pcs_internal = pcs.entry_points.internal:main",
        ],
    },
    cmdclass={
        "clean": CleanCommand,
        "scriptdir": ScriptDir,
        "platlib": PlatLib,
        "purelib": PureLib,
    },
)
