# coding: utf8

import os.path
import sqlalchemy as sa

from yandex.maps.wiki import db, fastcgihelpers as fh
from yandex.maps.wiki import config
from yandex.maps.wiki.pgpool3 import get_pgpool
from yandex.maps.wiki.tasks import EM
from yandex.maps.wiki.tasks import grinder
from yandex.maps.wiki.tasks import register_task_type
from yandex.maps.wiki.tasks.models import Task
from yandex.maps.wiki.utils import require

from maps.wikimap.mapspro.libs.python import acl

TASK_NAME = 'badge'

ACTION_ADD = 'add'
ACTION_REMOVE = 'remove'

ACL_PATH = "mpro/tasks/badge"


@register_task_type(name=TASK_NAME)
class Badge:
    @staticmethod
    def capabilities_ET():
        return EM.badge_task_type()

    @staticmethod
    def create(uid, request):
        require(acl.is_permission_granted(get_pgpool(db.CORE_DB), ACL_PATH, uid),
                fh.ServiceException('forbidden', status='ERR_FORBIDDEN'))

        task = BadgeTask()
        task.on_create(uid)

        require(request.files.values(),
                fh.ServiceException('File is not posted',
                                    status='ERR_BADGE_FILE_NOT_POSTED'))
        uploaded_file = request.files.values()[0]

        try:
            file_name, file_ext = os.path.splitext(uploaded_file.filename)
            require(file_ext == '.txt',
                    fh.ServiceException(
                        'Bad file name', status='ERR_BADGE_BAD_FILE_NAME'))

            task.badge_id, task.action = file_name.split('.')
            require(task.action in [ACTION_ADD, ACTION_REMOVE],
                    fh.ServiceException(
                        'Unknown action: ' + str(task.action),
                        status='ERR_BAD_REQUEST'))
        except:
            raise fh.ServiceException(
                'Bad file name', status='ERR_BADGE_BAD_FILE_NAME')

        task.file = uploaded_file.read()

        return task

    @staticmethod
    def launch(session, task_id, request):
        task = session.query(BadgeTask).get(task_id)
        args = {
            'type': TASK_NAME,
            'taskId': task_id,
            'action': task.action,
            'badgeId': task.badge_id
        }
        gateway = grinder.GrinderGateway(config.get_config().grinder_params.host)
        return gateway.submit(args)


class BadgeTask(Task):
    __mapper_args__ = {'polymorphic_identity': TASK_NAME}
    __tablename__ = 'badge_task'
    __table_args__ = {'schema': 'service'}

    id = sa.Column(sa.Integer,
                   sa.ForeignKey('service.task.id'),
                   primary_key=True)
    action = sa.Column(sa.String)
    badge_id = sa.Column(sa.String)
    file = sa.orm.deferred(sa.Column(sa.types.LargeBinary))
    result_url = sa.Column(sa.Text)

    def context_ET_brief(self, *args, **kwargs):
        return EM.badge_context(
            EM.action(self.action),
            EM.badge_id(self.badge_id))

    def result_ET_brief(self, *args, **kwargs):
        ret = EM.badge_result()
        if self.result_url:
            ret.append(EM.url(self.result_url))
        return ret
