#       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 logging
import urllib
import urllib2
from collections import defaultdict

from pkg_resources import iter_entry_points

from BeautifulSoup import BeautifulSoup
from tg import expose, validate, flash, redirect, config
from tg.decorators import with_trailing_slash
from pylons import tmpl_context as c, app_globals as g
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 import helpers as h
from allura.lib import exceptions
from allura.lib import validators as v
from allura.app import SitemapEntry

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(ProjectImportForm, self).__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.PlainText(not_empty=True)
    project_name = fev.UnicodeString(not_empty=True, max=40)


class ToolImportForm(schema.Schema):
    def __init__(self, tool_class):
        super(ToolImportForm, self).__init__()
        self.add_field('mount_point', v.MountPointValidator(tool_class))
    mount_label = fev.UnicodeString()


@task(notifications_disabled=True)
def import_tool(importer_name, project_name=None, mount_point=None, mount_label=None, **kw):
    importer = ToolImporter.by_name(importer_name)
    importer.import_tool(c.project, c.user, project_name=project_name,
            mount_point=mount_point, mount_label=mount_label, **kw)


class ProjectExtractor(object):
    """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,), **kw):
        req = urllib2.Request(url, **kw)
        req.add_header('User-Agent', 'Allura Data Importer (http://sf.net/p/allura)')
        return h.urlopen(req, retries=retries, codes=codes)

    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 = urllib.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)


class ProjectImporter(BaseController):
    """
    Base class for project importers.

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

    """
    source = None
    process_validator = None
    index_template = None

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

    def _check_security(self):
        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 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:
            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)
        for importer_name in kw['tools']:
            import_tool.post(importer_name, **kw)

        flash('Welcome to the %s Project System! '
              '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 ToolImporter(object):
    """
    Base class for tool importers.

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

    .. py:attribute:: target_app

       A reference or list of references to the tool(s) that this imports
       to.  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 = 'Google Code'

    .. 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 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 iter_entry_points('allura.importers'):
            importer = ep.load()
            if app in aslist(importer.target_app):
                importers[ep.name] = importer()
        return importers

    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_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)


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(ToolsValidator, self).__init__(*a, **kw)
        self.source = source

    def to_python(self, value, state=None):
        value = super(ToolsValidator, self).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(object):
    '''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()
        for ep in iter_entry_points('allura.importers'):
            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):
        import_tool = ToolImporter.by_name(name)
        if import_tool:
            return import_tool.controller(), 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)
