#       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 sys
import time
import traceback
import logging
from datetime import datetime, timedelta

import pymongo
from pylons import tmpl_context as c, app_globals as g
from tg import config
from paste.deploy.converters import asbool

import ming
from ming.utils import LazyProperty
from ming import schema as S
from ming.orm import session, FieldProperty
from ming.orm.declarative import MappedClass

from allura.lib.helpers import log_output
from .session import task_orm_session

log = logging.getLogger(__name__)


class MonQTask(MappedClass):

    '''Task to be executed by the taskd daemon.

    Properties

        - _id - bson.ObjectId() for this task
        - state - 'ready', 'busy', 'error', 'complete', or 'skipped' task status
        - priority - integer priority, higher is more priority
        - result_type - either 'keep' or 'forget', what to do with the task when
          it's done
        - time_queue - time the task was queued
        - time_start - time taskd began working on the task
        - time_stop - time taskd stopped working on the task
        - task_name - full dotted name of the task function to run
        - process - identifier for which taskd process is working on the task
        - context - values used to set c.project, c.app, c.user for the task
        - args - ``*args`` to be sent to the task function
        - kwargs - ``**kwargs`` to be sent to the task function
        - result - if the task is complete, the return value. If in error, the traceback.
    '''
    states = ('ready', 'busy', 'error', 'complete', 'skipped')
    result_types = ('keep', 'forget')

    class __mongometa__:
        session = task_orm_session
        name = 'monq_task'
        indexes = [
            [
                # used in MonQTask.get() method
                # also 'state' queries exist in several other methods
                ('state', ming.ASCENDING),
                ('priority', ming.DESCENDING),
                ('time_queue', ming.ASCENDING)
            ],
            [
                # used by SF internal tool, but could be generally useful to
                # have an index on task_name
                'state', 'task_name', 'time_queue'
            ],
            'args',
        ]

    _id = FieldProperty(S.ObjectId)
    state = FieldProperty(S.OneOf(*states))
    priority = FieldProperty(int)
    result_type = FieldProperty(S.OneOf(*result_types))
    time_queue = FieldProperty(datetime, if_missing=datetime.utcnow)
    time_start = FieldProperty(datetime, if_missing=None)
    time_stop = FieldProperty(datetime, if_missing=None)

    task_name = FieldProperty(str)
    process = FieldProperty(str)
    context = FieldProperty(dict(
        project_id=S.ObjectId,
        app_config_id=S.ObjectId,
        user_id=S.ObjectId,
        notifications_disabled=bool))
    args = FieldProperty([])
    kwargs = FieldProperty({None: None})
    result = FieldProperty(None, if_missing=None)

    def __repr__(self):
        from allura import model as M
        project = M.Project.query.get(_id=self.context.project_id)
        app = None
        if project:
            app_config = M.AppConfig.query.get(_id=self.context.app_config_id)
            if app_config:
                app = project.app_instance(app_config)
        user = M.User.query.get(_id=self.context.user_id)
        project_url = project and project.url() or None
        app_mount = app and app.config.options.mount_point or None
        username = user and user.username or None
        return '<%s %s (%s) P:%d %s %s project:%s app:%s user:%s>' % (
            self.__class__.__name__,
            self._id,
            self.state,
            self.priority,
            self.task_name,
            self.process,
            project_url,
            app_mount,
            username)

    @LazyProperty
    def function(self):
        '''The function that is called by this task'''
        smod, sfunc = self.task_name.rsplit('.', 1)
        cur = __import__(smod, fromlist=[sfunc])
        return getattr(cur, sfunc)

    @classmethod
    def post(cls,
             function,
             args=None,
             kwargs=None,
             result_type='forget',
             priority=10,
             delay=0):
        '''Create a new task object based on the current context.'''
        if args is None:
            args = ()
        if kwargs is None:
            kwargs = {}
        task_name = '%s.%s' % (
            function.__module__,
            function.__name__)
        context = dict(
            project_id=None,
            app_config_id=None,
            user_id=None,
            notifications_disabled=False)
        if getattr(c, 'project', None):
            context['project_id'] = c.project._id
            context[
                'notifications_disabled'] = c.project.notifications_disabled
        if getattr(c, 'app', None):
            context['app_config_id'] = c.app.config._id
        if getattr(c, 'user', None):
            context['user_id'] = c.user._id
        obj = cls(
            state='ready',
            priority=priority,
            result_type=result_type,
            task_name=task_name,
            args=args,
            kwargs=kwargs,
            process=None,
            result=None,
            context=context,
            time_queue=datetime.utcnow() + timedelta(seconds=delay))
        session(obj).flush(obj)
        try:
            if g.amq_conn:
                g.amq_conn.queue.put('')
        except:
            log.warning('Error putting to amq_conn', exc_info=True)
        return obj

    @classmethod
    def get(cls, process='worker', state='ready', waitfunc=None, only=None):
        '''Get the highest-priority, oldest, ready task and lock it to the
        current process.  If no task is available and waitfunc is supplied, call
        the waitfunc before trying to get the task again.  If waitfunc is None
        and no tasks are available, return None.  If waitfunc raises a
        StopIteration, stop waiting for a task
        '''
        sort = [
            ('priority', ming.DESCENDING),
            ('time_queue', ming.ASCENDING)]
        while True:
            try:
                query = dict(state=state)
                query['time_queue'] = {'$lte': datetime.utcnow()}
                if only:
                    query['task_name'] = {'$in': only}
                obj = cls.query.find_and_modify(
                    query=query,
                    update={
                        '$set': dict(
                            state='busy',
                            process=process)
                    },
                    new=True,
                    sort=sort)
                if obj is not None:
                    return obj
            except pymongo.errors.OperationFailure, exc:
                if 'No matching object found' not in exc.args[0]:
                    raise
            if waitfunc is None:
                return None
            try:
                waitfunc()
            except StopIteration:
                return None

    @classmethod
    def timeout_tasks(cls, older_than):
        '''Mark all busy tasks older than a certain datetime as 'ready' again.
        Used to retry 'stuck' tasks.'''
        spec = dict(state='busy')
        spec['time_start'] = {'$lt': older_than}
        cls.query.update(spec, {'$set': dict(state='ready')}, multi=True)

    @classmethod
    def clear_complete(cls):
        '''Delete the task objects for complete tasks'''
        spec = dict(state='complete')
        cls.query.remove(spec)

    @classmethod
    def run_ready(cls, worker=None):
        '''Run all the tasks that are currently ready'''
        i = 0
        for i, task in enumerate(cls.query.find(dict(state='ready')).all()):
            task.process = worker
            task()
        return i

    def __call__(self, restore_context=True):
        '''Call the task function with its context.  If restore_context is True,
        c.project/app/user will be restored to the values they had before this
        function was called.
        '''
        from allura import model as M
        self.time_start = datetime.utcnow()
        session(self).flush(self)
        log.info('starting %r', self)
        old_cproject = getattr(c, 'project', None)
        old_capp = getattr(c, 'app', None)
        old_cuser = getattr(c, 'user', None)
        try:
            func = self.function
            c.project = M.Project.query.get(_id=self.context.project_id)
            c.app = None
            if c.project:
                c.project.notifications_disabled = self.context.get(
                    'notifications_disabled', False)
                app_config = M.AppConfig.query.get(
                    _id=self.context.app_config_id)
                if app_config:
                    c.app = c.project.app_instance(app_config)
            c.user = M.User.query.get(_id=self.context.user_id)
            with log_output(log):
                self.result = func(*self.args, **self.kwargs)
            self.state = 'complete'
            return self.result
        except Exception, exc:
            if asbool(config.get('monq.raise_errors')):
                raise
            else:
                log.exception('Error "%s" on job %s', exc, self)
                self.state = 'error'
                if hasattr(exc, 'format_error'):
                    self.result = exc.format_error()
                    log.error(self.result)
                else:
                    self.result = traceback.format_exc()
        finally:
            self.time_stop = datetime.utcnow()
            session(self).flush(self)
            if restore_context:
                c.project = old_cproject
                c.app = old_capp
                c.user = old_cuser

    def join(self, poll_interval=0.1):
        '''Wait until this task is either complete or errors out, then return the result.'''
        while self.state not in ('complete', 'error'):
            time.sleep(poll_interval)
            self.query.find(dict(_id=self._id), refresh=True).first()
        return self.result

    @classmethod
    def list(cls, state='ready'):
        '''Print all tasks of a certain status to sys.stdout.  Used for debugging.'''
        for t in cls.query.find(dict(state=state)):
            sys.stdout.write('%r\n' % t)
