#!/usr/bin/env python
from common.util.clients import link_and_create_task, TaskError, StaffClient, CacheClient
from .base import Api
from api.util.loadscheme import LoadSchemeIterator
from common.models import Job, Server, LoadScheme, UploadToken, TankUserAgent
from django.http import HttpResponseForbidden, HttpResponse, HttpResponseBadRequest
from json import loads
from os import path
import logging
import re
import uuid

cur_dir = path.dirname(path.realpath(__file__))
directory_base = '/'.join(re.split('\/', cur_dir)[0:-2]) + '/'


class JobCreate(Api):
    http_method_names = ['post']

    @staticmethod
    def post(request):
        if CacheClient().get('maintenance'):
            return HttpResponse(status=423)
        params = request.body.decode('utf-8')
        if not params:
            return HttpResponseBadRequest('Params not set!')
        # 'task', 'person', 'tank', 'host', 'port', 'loadscheme', 'loadscheme_expanded', 'detailed_time', 'notify'

        params = loads(params)
        needed_params = ('task', 'person', 'tank', 'host', 'port')
        for np in needed_params:  # check all parameters are set
            if np not in params:
                return HttpResponseBadRequest('{} parameter not set!'.format(np))
        try:
            task = link_and_create_task(request, params['task'].strip().upper())
        except TaskError as e:
            return HttpResponseBadRequest(e)
        no_tank = 0
        try:  # tank
            tank = Server.objects.filter(host=params['tank'])
            assert tank
            tank = tank[0]
        except AssertionError:  # create it
            no_tank = 1
            tank = Server(host=params['tank'], is_test=1)
            tank.save()
        # was in database and not marked as a tank - mark
        if not no_tank and not tank.is_test:
            tank.is_test = 1
            tank.save()
        try:  # target
            srv = Server.objects.filter(host=params['host'])
            assert srv
            srv = srv[0]
        except AssertionError:  # create
            srv = Server(host=params['host'])
            srv.save()
        # if params['person'] != 'lunapark' and 'robot' not in params['person']:  # tankman
        #     try:
        #         staff_client = StaffClient()
        #         user_info = staff_client.get_user_info(params['person'], ['official.is_dismissed'])
        #         assert user_info.get('result', []) and not user_info['result'][0]['official']['is_dismissed']
        #     except AssertionError:
        #         return HttpResponseForbidden('No such tankman!')
        #     except Exception:
        #         logging.exception('Failed to check person on staff', exc_info=True)
        #         return HttpResponseForbidden('No such tankman!')
        job = Job(
            person=params['person'],
            task=task.key,
            tank=tank,
            srv=srv,
            srv_port=params['port'] if str(params['port']).isdigit() else 80,
            instances=0,
            name=params.get('name', ''),
            finalized=0,
        )
        job.save()

        try:
            user_agent = request.META.get('HTTP_USER_AGENT', '').strip()
            if re.match('^(Lunapark|Uploader)/.+ YandexTank/.+ Python/.+ OS/.+', user_agent):
                TankUserAgent.objects.create(job=job, user_agent=user_agent)
        except:
            logging.exception('')

        token = uuid.uuid4().hex
        UploadToken.objects.create(job=job.n, token=token)

        try:
            loadscheme = params.get('loadscheme', '')
            if loadscheme and isinstance(loadscheme, list): 
                if isinstance(loadscheme[0], dict) and 'type' in loadscheme[0]:
                    schemes = ['{type}({ops},{duration})'.format(type=scheme.get('type', ''), duration=scheme.get('duration', 1), ops=','.join([str(scheme[key]) for key in sorted(scheme.keys()) if key not in ('type', 'duration')])) for scheme in loadscheme]
                    [LoadScheme(**ls).save() for ls in LoadSchemeIterator([scheme for scheme in schemes], job)]
                else:
                    [LoadScheme(**ls).save() for ls in LoadSchemeIterator([str(scheme) for scheme in loadscheme], job)]
        except Exception:
            logging.error('loadscheme is incorrect. \
            please note that Lunapark does not support fractional loadschemes yet.')
            logging.debug('Incorrect loadscheme ', exc_info=True)

        return [{'job': job.n, 'upload_token': token}]
