#       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 errno
import logging
from io import BytesIO

import six.moves.urllib.request
import six.moves.urllib.parse
import six.moves.urllib.error
from collections import defaultdict
import traceback
from six.moves.urllib.parse import urlparse
from six.moves.urllib.parse import unquote
from datetime import datetime
import six

from bs4 import BeautifulSoup
from tg import expose, validate, flash, redirect, config
from tg.decorators import with_trailing_slash
from tg import app_globals as g
from tg import tmpl_context as c
from formencode import validators as fev, schema
from webob import exc

from allura.lib.decorators import require_post
from allura.lib.decorators import task
from allura.lib.security import require_access
from allura.lib.plugin import ProjectRegistrationProvider, AdminExtension
from allura.lib.utils import guess_mime_type
from allura.lib import helpers as h
from allura.lib import exceptions
from allura.lib import validators as v
from allura.app import SitemapEntry
from allura import model as M

from paste.deploy.converters import aslist

from ming.utils import LazyProperty
from allura.controllers import BaseController


log = logging.getLogger(__name__)


class ProjectImportForm(schema.Schema):

    def __init__(self, source):
        super().__init__()
        provider = ProjectRegistrationProvider.get()
        self.add_field('tools', ToolsValidator(source))
        self.add_field('project_shortname', provider.shortname_validator)
        self.allow_extra_fields = True

    neighborhood = fev.NotEmpty()
    project_name = v.UnicodeString(not_empty=True, max=40)


class ToolImportForm(schema.Schema):

    def __init__(self, tool_class):
        super().__init__()
        self.add_field('mount_point', v.MountPointValidator(tool_class))
    mount_label = v.UnicodeString()


class ImportErrorHandler:

    def __init__(self, importer, project_name, project):
        self.importer = importer
        self.project_name = project_name
        self.project = project

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if hasattr(self.importer, 'clear_pending'):
            self.importer.clear_pending(self.project)
        if exc_type:
            g.post_event('import_tool_task_failed',
                         error=str(exc_val),
                         traceback=traceback.format_exc(),
                         importer_source=self.importer.source,
                         importer_tool_label=self.importer.tool_label,
                         project_name=self.project_name,
                         )

    def success(self, app):
        with h.push_config(c, project=self.project, app=app):
            g.post_event('import_tool_task_succeeded',
                         self.importer.source,
                         self.importer.tool_label,
                         )


def object_from_path(path):
    """Given a dotted path, import and return the object at that path.

    """
    module_name, obj_name = path.rsplit('.', 1)
    module = __import__(module_name, fromlist=[obj_name])
    return getattr(module, obj_name)


@task(notifications_disabled=True)
def import_tool(importer_path, project_name=None,
                mount_point=None, mount_label=None, **kw):
    importer = object_from_path(importer_path)()
    with ImportErrorHandler(importer, project_name, c.project) as handler,\
            M.session.substitute_extensions(M.artifact_orm_session,
                                            [M.session.BatchIndexer]):
        try:
            M.artifact_orm_session._get().skip_last_updated = True
            app = importer.import_tool(
                c.project, c.user, project_name=project_name,
                mount_point=mount_point, mount_label=mount_label, **kw)
            # manually update project's last_updated field at the end of the
            # import instead of it being updated automatically by each artifact
            # since long-running task can cause stale project data to be saved
            M.Project.query.update(
                {'_id': c.project._id},
                {'$set': {'last_updated': datetime.utcnow()}})
        finally:
            M.artifact_orm_session._get().skip_last_updated = False
        M.artifact_orm_session.flush()
        M.session.BatchIndexer.flush()
        if app:
            with h.notifications_disabled(c.project, disabled=False):
                g.director.create_activity(c.user, "imported", app.config,
                                           related_nodes=[c.project], tags=['import'])
            handler.success(app)


class ProjectExtractor:

    """Base class for project extractors.

    Subclasses should use :meth:`urlopen` to make HTTP requests, as it provides
    a custom User-Agent and automatically retries timed-out requests.

    """

    PAGE_MAP = {}

    def __init__(self, project_name, page_name=None, **kw):
        self.project_name = project_name
        self._page_cache = {}
        self.url = None
        self.page = None
        if page_name:
            self.get_page(page_name, **kw)

    @staticmethod
    def urlopen(url, retries=3, codes=(408, 500, 502, 503, 504), timeout=120, unredirected_hdrs=None, **kw):
        req = six.moves.urllib.request.Request(url, **kw)
        if unredirected_hdrs:
            for key, val in unredirected_hdrs.items():
                req.add_unredirected_header(key, val)
        req.add_header('User-Agent', 'Allura Data Importer (https://allura.apache.org/)')
        return h.urlopen(req, retries=retries, codes=codes, timeout=timeout)

    def get_page(self, page_name_or_url, parser=None, **kw):
        """Return a Beautiful soup object for the given page name or url.

        If a page name is provided, the associated url is looked up in
        :attr:`PAGE_MAP`.

        If provided, the class or callable passed in :param:`parser` will be
        used to transform the result of the `urlopen` before returning it.
        Otherwise, the class's :meth:`parse_page` will be used.

        Results are cached so that subsequent calls for the same page name or
        url will return the cached result rather than making another HTTP
        request.

        """
        if page_name_or_url in self.PAGE_MAP:
            self.url = self.get_page_url(page_name_or_url, **kw)
        else:
            self.url = page_name_or_url
        if self.url in self._page_cache:
            self.page = self._page_cache[self.url]
        else:
            if parser is None:
                parser = self.parse_page
            self.page = self._page_cache[self.url] = \
                parser(self.urlopen(self.url))
        return self.page

    def get_page_url(self, page_name, **kw):
        """Return the url associated with ``page_name``.

        Raises KeyError if ``page_name`` is not in :attr:`PAGE_MAP`.

        """
        return self.PAGE_MAP[page_name].format(
            project_name=six.moves.urllib.parse.quote(self.project_name), **kw)

    def parse_page(self, page):
        """Transforms the result of a `urlopen` call before returning it from
        :meth:`get_page`.

        The default implementation create a :class:`BeautifulSoup` object from
        the html.

        Subclasses can override to change the behavior or handle other types
        of content (like JSON).  The parser can also be overridden via the
        `parser` parameter to :meth:`get_page`

        :param page: A file-like object return from :meth:`urlopen`

        """
        return BeautifulSoup(page, convertEntities=BeautifulSoup.HTML_ENTITIES)


class ProjectImporter(BaseController):

    """
    Base class for project importers.

    Subclasses are required to implement the :meth:`index()` and
    :meth:`process()` views described below.

    """
    source = None
    tool_label = 'Project Info'
    process_validator = None
    index_template = None

    def __init__(self, neighborhood, *a, **kw):
        self.neighborhood = neighborhood

    def _check_security(self):
        with h.login_overlay(exceptions=['process']):
            require_access(self.neighborhood, 'register')

    @LazyProperty
    def tool_importers(self):
        """
        List of all tool importers that import from the same source
        as this project importer.
        """
        tools = {}
        for ep in h.iter_entry_points('allura.importers'):
            epv = ep.load()
            if epv.source == self.source:
                tools[ep.name] = epv()
        return tools

    @with_trailing_slash
    @expose()
    def index(self, **kw):
        """
        Override and expose this view to present the project import form.

        The template used by this view should extend the base template in::

            jinja:forgeimporters:templates/project_base.html

        This will list the available tool importers.  Other project fields
        (e.g., project_name) should go in the project_fields block.
        """
        return {'importer': self, 'tg_template': self.index_template}

    @require_post()
    @expose()
    @validate(process_validator, error_handler=index)
    def process(self, **kw):
        """
        Override and expose this to handle a project import.

        This should at a minimum create the stub project with the appropriate
        tools installed and redirect to the new project, presumably with a
        message indicating that some data will not be available immediately.
        """
        try:
            with h.push_config(config, **{'project.verify_phone': 'false'}):
                c.project = self.neighborhood.register_project(
                    kw['project_shortname'],
                    project_name=kw['project_name'])
        except exceptions.ProjectOverlimitError:
            flash("You have exceeded the maximum number of projects you are allowed to create", 'error')
            redirect('.')
        except exceptions.ProjectRatelimitError:
            flash("Project creation rate limit exceeded.  Please try again later.", 'error')
            redirect('.')
        except Exception:
            log.error('error registering project: %s',
                      kw['project_shortname'], exc_info=True)
            flash('Internal Error. Please try again later.', 'error')
            redirect('.')

        self.after_project_create(c.project, **kw)
        tools = aslist(kw.get('tools'))

        for importer_name in tools:
            ToolImporter.by_name(importer_name).post(**kw)
        M.AuditLog.log('import project from %s' % self.source)

        flash('Welcome to your new project on %s! '
              'Your project data will be imported and should show up here shortly.' % config['site_name'])
        redirect(c.project.script_name + 'admin/overview')

    @expose('json:')
    @validate(process_validator)
    def check_names(self, **kw):
        """
        Ajax form validation.

        """
        return c.form_errors

    def after_project_create(self, project, **kw):
        """
        Called after project is created.

        Useful for doing extra processing on the project before individual
        tool imports happen.

        :param project: The newly created project.
        :param **kw: The keyword arguments that were posted to the controller
            method that created the project.

        """
        pass


class ToolImportControllerMeta(type):
    def __call__(cls, importer, *args, **kw):
        """ Decorate the `create` post handler with a validator that references
        the appropriate App for this controller's importer.

        """
        if hasattr(cls, 'create') and getattr(cls.create.decoration, 'validation', None) is None:
            index_meth = getattr(cls.index, '__func__', cls.index)
            cls.create = validate(cls.import_form(aslist(importer.target_app)[0]),
                                  error_handler=index_meth)(cls.create)
        return type.__call__(cls, importer, *args, **kw)


class ToolImportController(BaseController, metaclass=ToolImportControllerMeta):
    """ Base class for ToolImporter controllers.

    """

    def __init__(self, importer):
        """
        :param importer: :class:`ToolImporter` instance to which this
            controller belongs.

        """
        self.importer = importer

    @property
    def target_app(self):
        return aslist(self.importer.target_app)[0]


class ToolImporterMeta(type):
    def __init__(cls, name, bases, attrs):
        if not (hasattr(cls, 'target_app_ep_names')
                or hasattr(cls, 'target_app')):
            raise AttributeError(f"{name} must define either `target_app` or `target_app_ep_names`")
        return type.__init__(cls, name, bases, attrs)

    def __call__(cls, *args, **kw):
        """ Right before the first instance of cls is created, get
        the list of target_app classes from ep names. Can't do this
        at cls create/init time b/c g.entry_points is not guaranteed
        to be loaded at that point.

        """
        if not getattr(cls, 'target_app', None):
            cls.target_app = [g.entry_points['tool'][ep_name]
                              for ep_name in aslist(cls.target_app_ep_names)
                              if ep_name in g.entry_points['tool']]
        return type.__call__(cls, *args, **kw)


class ToolImporter(metaclass=ToolImporterMeta):

    """
    Base class for tool importers.

    Subclasses are required to implement :meth:`import_tool()` described
    below and define the following attributes:

    .. py:attribute:: target_app_ep_names

       A string or list of strings which are entry point names of the
       tool(s) to which this class imports. E.g.::

            target_app_ep_names = ['git', 'hg']

    .. py:attribute:: target_app

       A reference or list of references to the tool(s) that this imports
       to.  This attribute is not required if `target_app_ep_names` is
       defined (which is preferable). E.g.::

            target_app = [forgegit.ForgeGitApp, forgehg.ForgeHgApp]

    .. py:attribute:: source

       A string indicating where this imports from.  This must match the
       `source` value of the :class:`ProjectImporter` for this importer to
       be discovered during full-project imports.  E.g.::

            source = 'GitHub'

    .. py:attribute:: controller

       The controller for this importer, to handle single tool imports.

    """

    target_app = None  # app or list of apps
    source = None  # string description of source, must match project importer
    controller = None

    @staticmethod
    def by_name(name):
        """
        Return a ToolImporter subclass instance given its entry-point name.
        """
        for ep in h.iter_entry_points('allura.importers', name):
            return ep.load()()

    @staticmethod
    def by_app(app):
        """
        Return a ToolImporter subclass instance given its target_app class.
        """
        importers = {}
        for ep in h.iter_entry_points('allura.importers'):
            importer = ep.load()
            if app in aslist(importer.target_app):
                importers[ep.name] = importer()
        return importers

    @property
    def classname(self):
        return self.__class__.__name__

    def enforce_limit(self, project):
        """
        Enforce rate limiting of tool imports on a given project.

        Returns False if limit is met / exceeded.  Otherwise, increments the
        count of pending / in-progress imports and returns True.
        """
        limit = config.get('tool_import.rate_limit', 1)
        pending_key = 'tool_data.%s.pending' % self.classname
        modified_project = M.Project.query.find_and_modify(
            query={
                '_id': project._id,
                '$or': [
                    {pending_key: None},
                    {pending_key: {'$lt': limit}},
                ],
            },
            update={'$inc': {pending_key: 1}},
            new=True,
        )
        return modified_project is not None

    def clear_pending(self, project):
        """
        Decrement the pending counter for this importer on the given project,
        to indicate that an import is complete.
        """
        pending_key = 'tool_data.%s.pending' % self.classname
        M.Project.query.find_and_modify(
            query={'_id': project._id},
            update={'$inc': {pending_key: -1}},
            new=True,
        )

    def import_tool(self, project, user, project_name=None,
                    mount_point=None, mount_label=None, **kw):
        """
        Override this method to perform the tool import.

        :param project: the Allura project to import to
        :param project_name: the name of the remote project to import from
        :param mount_point: the mount point name, to override the default
        :param mount_label: the mount label name, to override the default
        """
        raise NotImplementedError

    @property
    def tool_label(self):
        """
        The label for this tool importer.  Defaults to the `tool_label` from
        the `target_app`.
        """
        return getattr(aslist(self.target_app)[0], 'tool_label', None)

    @property
    def tool_option(self):
        """
        The option for this tool importer. Defaults to the `tool_option` from
        the `target_app`.
        """
        return getattr(aslist(self.target_app)[0], 'tool_option', dict())

    @property
    def tool_description(self):
        """
        The description for this tool importer.  Defaults to the `tool_description`
        from the `target_app`.
        """
        return getattr(aslist(self.target_app)[0], 'tool_description', None)

    def tool_icon(self, theme, size):
        return theme.app_icon_url(aslist(self.target_app)[0], size)

    def post(self, **kw):
        """Post a task that will call ``import_tool()`` on this instance.

        """
        klass = self.__class__
        importer_path = f'{klass.__module__}.{klass.__name__}'
        import_tool.post(importer_path, **kw)


class ToolsValidator(fev.Set):

    """
    Validates the list of tool importers during a project import.

    This verifies that the tools selected are available and valid
    for this source.
    """

    def __init__(self, source, *a, **kw):
        super().__init__(*a, **kw)
        self.source = source

    def to_python(self, value, state=None):
        value = super().to_python(value, state)
        valid = []
        invalid = []
        for name in value:
            importer = ToolImporter.by_name(name)
            if importer is not None and importer.source == self.source:
                valid.append(name)
            else:
                invalid.append(name)
        if invalid:
            pl = 's' if len(invalid) > 1 else ''
            raise fev.Invalid('Invalid tool%s selected: %s' %
                              (pl, ', '.join(invalid)), value, state)
        return valid


class ProjectToolsImportController:

    '''List all importers available'''

    @with_trailing_slash
    @expose('jinja:forgeimporters:templates/list_all.html')
    def index(self, *a, **kw):
        importer_matrix = defaultdict(dict)
        tools_with_importers = set()
        hidden = set(aslist(config.get('hidden_importers'), sep=','))
        visible = lambda ep: ep.name not in hidden
        for ep in filter(visible, h.iter_entry_points('allura.importers')):
            # must instantiate to ensure importer.target_app is populated
            # (see ToolImporterMeta.__call__)
            importer = ep.load()()
            for tool in aslist(importer.target_app):
                tools_with_importers.add(tool.tool_label)
                importer_matrix[importer.source][tool.tool_label] = ep.name
        return {
            'importer_matrix': importer_matrix,
            'tools': tools_with_importers,
        }

    @expose()
    def _lookup(self, name, *remainder):
        importer = ToolImporter.by_name(name)
        if importer:
            return importer.controller(importer), remainder
        else:
            raise exc.HTTPNotFound


class ImportAdminExtension(AdminExtension):

    '''Add import link to project admin sidebar'''

    project_admin_controllers = {'import': ProjectToolsImportController}

    def update_project_sidebar_menu(self, sidebar_links):
        base_url = c.project.url() + 'admin/ext/'
        link = SitemapEntry('Import', base_url + 'import/')
        sidebar_links.append(link)


def bytesio_parser(page):
    return {
        'content-type': page.info()['content-type'],
        'data': BytesIO(page.read()),
    }


class File:

    def __init__(self, url, filename=None):
        extractor = ProjectExtractor(None, url, parser=bytesio_parser)
        self.url = url
        self.filename = filename or unquote(os.path.basename(urlparse(url).path))
        # try to get the mime-type from the filename first, because
        # some files (e.g., attachements) may have the Content-Type header
        # forced to encourage the UA to download / save the file
        self.type = guess_mime_type(self.filename)
        if self.type == 'application/octet-stream':
            # however, if that fails, fall back to the given mime-type,
            # as some files (e.g., project icons) might have no file
            # extension but return a valid Content-Type header
            self.type = extractor.page['content-type']
        self.file = extractor.page['data']


def get_importer_upload_path(project):
    shortname = project.shortname
    if project.is_nbhd_project:
        shortname = project.url().strip('/')
    elif project.is_user_project:
        shortname = project.shortname.split('/')[1]
    elif not project.is_root:
        shortname = project.shortname.split('/')[0]
    upload_path = config['importer_upload_path'].format(
        nbhd=project.neighborhood.url_prefix.strip('/'),
        project=shortname,
        c=c,
    )
    return upload_path


def save_importer_upload(project, filename, data):
    dest_path = get_importer_upload_path(project)
    dest_file = os.path.join(dest_path, filename)
    try:
        os.makedirs(dest_path)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise
    with open(dest_file, 'w', encoding='utf-8') as fp:
        fp.write(data)
    return dest_file
