# -*- coding: UTF-8 -*-
from api.models import Gadget, Region, City
from api.models import GadgetCity, GadgetRegion
from django.db import IntegrityError, transaction
import json
from gm_types.gaia import SLIDE_TYPE
from rpc.decorators import bind_context
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.dict_mixin import to_dict
from rpc.tool.log_tool import info_logger, logging_exception
from ..datatables import GadgetDT
from ..queries.gadget import GadgetDQ
from api.models.special import Special

uri_pre = 'hera/gadget'


@bind_context(uri_pre + '/query')
def gadget_query(ctx, options):
    dqobj = GadgetDQ()
    return dqobj.process(**options)


@bind_context(uri_pre+'/list')
def gadget_datatable(ctx, req_data):
    dtobj = GadgetDT(Gadget)
    return dtobj.process(req_data)


@bind_context(uri_pre+'/get')
def gadget_detail(ctx, gadget_id, options=None):
    try:
        gadget = Gadget.objects.get(id=gadget_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    gadget_data = to_dict(gadget, **options)
    gadget_data['image_data'] = json.loads(gadget.image_data)
    return gadget_data


@transaction.atomic
@bind_context(uri_pre+'/edit')
def gadget_edit(ctx, gadget_id=None, gadget_info=None):
    if gadget_info is None:
        return None

    region_ids = gadget_info.pop('region')
    city_ids = gadget_info.pop('city')
    image_data = json.loads(gadget_info.pop('image_data', ""))

    for key, _d in image_data.iteritems():
        url_type = _d.get('url_type', -1)
        url_params = _d.get('url_params', {})
        if url_type == SLIDE_TYPE.SPECIAL and url_params:
            special_id = url_params.get('id')
            s = Special.objects.get(id=special_id)
            if s.is_new_special:
                url_params['is_new_special'] = '1'
            else:
                url_params['is_new_special'] = '0'

    gadget_info['image_data'] = json.dumps(image_data)
    if gadget_id is None:
        try:
            gadget = Gadget.objects.create(**gadget_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            gadget = Gadget.objects.get(id=gadget_id)
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException
        for k, v in gadget_info.iteritems():
            setattr(gadget, k, v)
        gadget.save()

    new_region = set(Region.objects.filter(id__in=region_ids))
    old_region = set(gadget.region.all())
    for region in (new_region - old_region):
        GadgetRegion.objects.get_or_create(gadget=gadget, region=region)
    GadgetRegion.objects.filter(gadget=gadget, region__in=(old_region-new_region)).delete()

    new_city = set(City.objects.filter(id__in=city_ids))
    old_city = set(gadget.city.all())
    for city in (new_city - old_city):
        GadgetCity.objects.get_or_create(gadget=gadget, city=city)
    GadgetCity.objects.filter(gadget=gadget, city__in=(old_city-new_city)).delete()
    return gadget.id


@bind_context(uri_pre + '/replication_gadget')
def replication_gadget(ctx, gadget_id):
    """复制固定模版"""
    new_gadget = None
    gadget = Gadget.objects.get(id=gadget_id)
    region_ids = GadgetRegion.objects.filter(gadget=gadget).values_list('region_id', flat=True)
    city_ids = GadgetCity.objects.filter(gadget=gadget).values_list('city_id', flat=True)
    with transaction.atomic():
        try:
            new_gadget_data = to_dict(
                gadget, excludes=[
                    'id', 'gadgetregion', 'gadgetcity',
                    'categorygadget', 'polymer', 'city',
                    'region', 'image_data']
            )

            new_gadget = Gadget.objects.create(**new_gadget_data)
            new_gadget.image_data = gadget.image_data
            new_gadget.save()
            gtoregions = [GadgetRegion(gadget=new_gadget, region_id=region_id)
                         for region_id in region_ids]
            GadgetRegion.objects.bulk_create(gtoregions)

            gadget_objs = [GadgetCity(gadget=new_gadget, city_id=city_id)
                       for city_id in city_ids]
            GadgetCity.objects.bulk_create(gadget_objs)
        except Exception as e:
            logging_exception()
            raise e

    return {'id': new_gadget.id}


@bind_context(uri_pre + '/copy')
@transaction.atomic
def gadget_copy(ctx, gadget_id=None):
    if gadget_id:
        try:
            with transaction.atomic():
                gadget = Gadget.objects.get(id=gadget_id)
                gadget_info = to_dict(gadget)
                gadget_info.pop('id')
                citys = gadget_info.pop('city')
                regions = gadget_info.pop('region')
                gadget_info.pop('gadgetcity')
                gadget_info.pop('gadgetregion')
                online_info = {'is_online': False}
                image_data = {'image_data': gadget.image_data}
                gadget_info.update(online_info)
                gadget_info.update(image_data)
                gadget_create = Gadget.objects.create(**gadget_info)
                for region_id in regions:
                    GadgetRegion.objects.create(gadget=gadget_create, region_id=region_id)
                for city_id in citys:
                    GadgetCity.objects.create(gadget=gadget_create, city_id=city_id)
        except IntegrityError:
            raise RPCIntegrityError
        except:
            raise RPCNotFoundException
    if gadget_create:
        return gadget_create.id
    return None
