# -*- coding: utf-8 -*-
"""
    wechatpyyyy.messages
    ~~~~~~~~~~~~~~~~~~

    This module defines all the messages you can get from WeChat server

    :copyright: (c) 2014 by messense.
    :license: MIT, see LICENSE for more details.
"""
from __future__ import absolute_import, unicode_literals
import copy
import six

from wechatpyyyy.fields import (
    BaseField,
    StringField,
    IntegerField,
    DateTimeField,
    FieldDescriptor
)
from wechatpyyyy.utils import to_text, to_binary


MESSAGE_TYPES = {}


def register_message(msg_type):
    def register(cls):
        MESSAGE_TYPES[msg_type] = cls
        return cls
    return register


class MessageMetaClass(type):
    """Metaclass for all messages"""
    def __new__(cls, name, bases, attrs):
        for b in bases:
            if not hasattr(b, '_fields'):
                continue

            for k, v in b.__dict__.items():
                if k in attrs:
                    continue
                if isinstance(v, FieldDescriptor):
                    attrs[k] = copy.deepcopy(v.field)

        cls = super(MessageMetaClass, cls).__new__(cls, name, bases, attrs)
        cls._fields = {}

        for name, field in cls.__dict__.items():
            if isinstance(field, BaseField):
                field.add_to_class(cls, name)
        return cls


class BaseMessage(six.with_metaclass(MessageMetaClass)):
    """Base class for all messages and events"""
    type = 'unknown'
    id = IntegerField('MsgId', 0)
    source = StringField('FromUserName')
    target = StringField('ToUserName')
    create_time = DateTimeField('CreateTime')
    time = IntegerField('CreateTime')

    def __init__(self, message):
        self._data = message

    def __repr__(self):
        _repr = "{klass}({msg})".format(
            klass=self.__class__.__name__,
            msg=repr(self._data)
        )
        if six.PY2:
            return to_binary(_repr)
        else:
            return to_text(_repr)


@register_message('text')
class TextMessage(BaseMessage):
    """
    文本消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'text'
    content = StringField('Content')


@register_message('image')
class ImageMessage(BaseMessage):
    """
    图片消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'image'
    media_id = StringField('MediaId')
    image = StringField('PicUrl')


@register_message('voice')
class VoiceMessage(BaseMessage):
    """
    语音消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'voice'
    media_id = StringField('MediaId')
    format = StringField('Format')
    recognition = StringField('Recognition')


@register_message('shortvideo')
class ShortVideoMessage(BaseMessage):
    """
    短视频消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'shortvideo'
    media_id = StringField('MediaId')
    thumb_media_id = StringField('ThumbMediaId')


@register_message('video')
class VideoMessage(BaseMessage):
    """
    视频消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'video'
    media_id = StringField('MediaId')
    thumb_media_id = StringField('ThumbMediaId')


@register_message('location')
class LocationMessage(BaseMessage):
    """
    地理位置消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'location'
    location_x = StringField('Location_X')
    location_y = StringField('Location_Y')
    scale = StringField('Scale')
    label = StringField('Label')

    @property
    def location(self):
        return self.location_x, self.location_y


@register_message('link')
class LinkMessage(BaseMessage):
    """
    链接消息
    详情请参阅
    http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
    """
    type = 'link'
    title = StringField('Title')
    description = StringField('Description')
    url = StringField('Url')


@register_message('miniprogrampage')
class MiniProgramPageMessage(BaseMessage):
    """
    小程序卡片消息
    详情请参阅
    https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/receive.html#小程序卡片消息
    """
    type = 'miniprogrampage'
    app_id = StringField('AppId')
    title = StringField('Title')
    page_path = StringField('PagePath')
    thumb_url = StringField('ThumbUrl')
    thumb_media_id = StringField('ThumbMediaId')


class UnknownMessage(BaseMessage):
    """未知消息类型"""
    pass
