# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 os
import tempfile
import subprocess
import sys
import zipfile
from datetime import datetime

import wagon

from . import exceptions
from ..utils import process as process_utils

_IS_WIN = os.name == 'nt'


class PluginManager(object):

    def __init__(self, model, plugins_dir):
        """
        :param plugins_dir: Root directory to install plugins in.
        """
        self._model = model
        self._plugins_dir = plugins_dir

    def install(self, source):
        """
        Install a wagon plugin.
        """
        metadata = wagon.show(source)
        cls = self._model.plugin.model_cls

        os_props = metadata['build_server_os_properties']

        plugin = cls(
            name=metadata['package_name'],
            archive_name=metadata['archive_name'],
            supported_platform=metadata['supported_platform'],
            supported_py_versions=metadata['supported_python_versions'],
            distribution=os_props.get('distribution'),
            distribution_release=os_props['distribution_version'],
            distribution_version=os_props['distribution_release'],
            package_name=metadata['package_name'],
            package_version=metadata['package_version'],
            package_source=metadata['package_source'],
            wheels=metadata['wheels'],
            uploaded_at=datetime.now()
        )
        if len(self._model.plugin.list(filters={'package_name': plugin.package_name,
                                                'package_version': plugin.package_version})):
            raise exceptions.PluginAlreadyExistsError(
                'Plugin {0}, version {1} already exists'.format(plugin.package_name,
                                                                plugin.package_version))
        self._install_wagon(source=source, prefix=self.get_plugin_dir(plugin))
        self._model.plugin.put(plugin)
        return plugin

    def load_plugin(self, plugin, env=None):
        """
        Load the plugin into an environment.
        Loading the plugin means the plugin's code and binaries paths will be appended to the
        environment's PATH and PYTHONPATH, thereby allowing usage of the plugin.
        :param plugin: The plugin to load
        :param env: The environment to load the plugin into; If `None`, os.environ will be used.
        """
        env = env or os.environ
        plugin_dir = self.get_plugin_dir(plugin)

        # Update PATH environment variable to include plugin's bin dir
        bin_dir = 'Scripts' if _IS_WIN else 'bin'
        process_utils.append_to_path(os.path.join(plugin_dir, bin_dir), env=env)

        # Update PYTHONPATH environment variable to include plugin's site-packages
        # directories
        if _IS_WIN:
            pythonpath_dirs = [os.path.join(plugin_dir, 'Lib', 'site-packages')]
        else:
            # In some linux environments, there will be both a lib and a lib64 directory
            # with the latter, containing compiled packages.
            pythonpath_dirs = [os.path.join(
                plugin_dir, 'lib{0}'.format(b),
                'python{0}.{1}'.format(sys.version_info[0], sys.version_info[1]),
                'site-packages') for b in ('', '64')]

        process_utils.append_to_pythonpath(*pythonpath_dirs, env=env)

    def get_plugin_dir(self, plugin):
        return os.path.join(
            self._plugins_dir,
            '{0}-{1}'.format(plugin.package_name, plugin.package_version))

    @staticmethod
    def validate_plugin(source):
        """
        validate a plugin archive.
        A valid plugin is a wagon (http://github.com/cloudify-cosmo/wagon)
        in the zip format (suffix may also be .wgn).
        """
        if not zipfile.is_zipfile(source):
            raise exceptions.InvalidPluginError(
                'Archive {0} is of an unsupported type. Only '
                'zip/wgn is allowed'.format(source))
        with zipfile.ZipFile(source, 'r') as zip_file:
            infos = zip_file.infolist()
            try:
                package_name = infos[0].filename[:infos[0].filename.index('/')]
                package_json_path = "{0}/{1}".format(package_name, 'package.json')
                zip_file.getinfo(package_json_path)
            except (KeyError, ValueError, IndexError):
                raise exceptions.InvalidPluginError(
                    'Failed to validate plugin {0} '
                    '(package.json was not found in archive)'.format(source))

    def _install_wagon(self, source, prefix):
        pip_freeze_output = self._pip_freeze()
        file_descriptor, constraint_path = tempfile.mkstemp(prefix='constraint-', suffix='.txt')
        os.close(file_descriptor)
        try:
            with open(constraint_path, 'wb') as constraint:
                constraint.write(pip_freeze_output)
            # Install the provided wagon.
            # * The --prefix install_arg will cause the plugin to be installed under
            #   plugins_dir/{package_name}-{package_version}, So different plugins don't step on
            #   each other and don't interfere with the current virtualenv
            # * The --constraint flag points a file containing the output of ``pip freeze``.
            #   It is required, to handle cases where plugins depend on some python package with
            #   a different version than the one installed in the current virtualenv. Without this
            #   flag, the existing package will be **removed** from the parent virtualenv and the
            #   new package will be installed under prefix. With the flag, the existing version will
            #   remain, and the version requested by the plugin will be ignored.
            wagon.install(
                source=source,
                install_args='--prefix="{prefix}" --constraint="{constraint}"'.format(
                    prefix=prefix,
                    constraint=constraint.name),
                venv=os.environ.get('VIRTUAL_ENV'))
        finally:
            os.remove(constraint_path)

    @staticmethod
    def _pip_freeze():
        """Run pip freeze in current environment and return the output"""
        bin_dir = 'Scripts' if os.name == 'nt' else 'bin'
        pip_path = os.path.join(sys.prefix, bin_dir,
                                'pip{0}'.format('.exe' if os.name == 'nt' else ''))
        pip_freeze = subprocess.Popen([pip_path, 'freeze'], stdout=subprocess.PIPE)
        pip_freeze_output, _ = pip_freeze.communicate()
        assert not pip_freeze.poll()
        return pip_freeze_output
