"""
A simple plugin to record waken people and return order of waking.
"""
import logging
from . import TimerBot
from datetime import datetime, date
from threading import Lock
from redis_variable import RedisVariable

logger = logging.getLogger(__name__)


class ZaoBot(TimerBot):
    def __init__(self, *args, **kwargs):
        self.new_day()
        # map id to Name
        self.guys_mapping = RedisVariable('zaobot:guys_mapping')
        self.lock = Lock()
        super().__init__(*args, **kwargs)

    def _list_guys(self):
        '''
        return list of guys as tuple(`name`, `time`) which is sorted by date
        '''
        result = self.waken_guys.zrange(0, -1, withscores=True)
        logger.debug('list_guys: result from redis is {}'.format(result))

        # Transform result from redis ( (timestamp(byte), id(byte)) )
        # to result we need ( (name(str), time(datetime)) )
        def trans_func(id_timestamp):
            uid, timestamp = id_timestamp
            name = self.guys_mapping.hget(int(uid)).decode(encoding='UTF-8')
            logger.debug('list_guys: id -> name {}:{}'.format(uid, name))
            logger.debug('type of name: {}'.format(type(name)))
            time = datetime.fromtimestamp(int(timestamp))
            return (name, time)

        ret = map(trans_func, result)
        # logger.debug('list_guys: result after map is {}'.format(list(ret)))
        return list(ret)

    def _who(self, user):
        return '少年'

    def new_day(self):
        today = str(date.today())
        self.waken_guys = RedisVariable('zaobot:waken_guys:{}'.format(today))
        self.sleep_guys = RedisVariable('zaobot:sleep_guys:{}'.format(today))

    def save_user(self, user):
        '''
        save name of user to redis
        '''
        if user.last_name is None:
            name = user.first_name
        else:
            name = '{} {}'.format(user.first_name, user.last_name)
        self.guys_mapping.hset(user.id, name)

    def bind(self):
        @self.sched.scheduled_job('cron', hour='5')
        def clear_guys():
            self.new_day()

        @self.bot.message_handler(commands=['zaoguys', 'zaobirds', 'zaobugs'])
        def list_guys(message):
            sorted_guys = self._list_guys()
            logger.debug('sorted_guys is {}'.format(list(sorted_guys)))
            prefix = ""
            if message.text.startswith('/zaobugs'):
                prefix = "被鸟儿吃掉的虫子:\n"
            elif message.text.startswith('/zaobirds'):
                prefix = "被大鹰吃掉的鸟儿:\n"
            if sorted_guys:
                self.bot.send_message(
                    message.chat.id,
                    prefix + '\n'.join(
                        map(
                            lambda i_guy: '{}. {}, {:%H:%M}'.format(
                                i_guy[0]+1, *i_guy[1]),
                            enumerate(sorted_guys))))
            else:
                self.bot.reply_to(message, 'o<<(≧口≦)>>o 还没人起床')

        @self.bot.message_handler(commands=['wan'])
        def wan_handler(message):
            self.save_user(message.from_user)

            waken_time = self.waken_guys.zscore(message.from_user.id)
            first_sleep = self.sleep_guys.zscore(message.from_user.id)
            if first_sleep is None:
                # This is the first time of today to sleep
                self.sleep_guys.zadd(message.date, message.from_user.id)

            # Response
            if waken_time is None:
                self.bot.reply_to(
                    message, "Pia!<(=ｏ ‵-′)ノ☆ 不起床就睡，睡死你好了～")
            elif first_sleep is None:
                waken_datetime = datetime.fromtimestamp(int(waken_time))
                sleep_datetime = datetime.fromtimestamp(message.date)
                duration = sleep_datetime - waken_datetime
                self.bot.reply_to(
                    message,
                    "今日共清醒{}秒，辛苦了".format(duration.total_seconds()))
            else:
                first_sleep_datetime = datetime.fromtimestamp(int(first_sleep))
                this_sleep_datetime = datetime.fromtimestamp(message.date)
                duration = this_sleep_datetime - first_sleep_datetime
                self.bot.reply_to(
                    message,
                    "关机失败{}秒 Pia!<(=ｏ ‵-′)ノ☆".format(
                        duration.total_seconds()))

        @self.bot.message_handler(commands=['zao'])
        def zao_handler(message):
            self.save_user(message.from_user)

            with self.lock:
                # There seems no way to determine whether an element in
                # sorted set except trying to retrieve it.
                rank = self.waken_guys.zrank(message.from_user.id)
                index = self.waken_guys.zcard()
                if rank is None:
                    self.waken_guys.zadd(message.date, message.from_user.id)
                    rewaken = False
                else:
                    rewaken = True

            # Send response
            if rewaken:
                self.bot.reply_to(message, "Pia!<(=ｏ‵-′)ノ☆  你不是起床过了吗?")
            else:
                if index == 0:
                    self.bot.reply_to(message, "✔ 获得成就[最早起床]")
                else:
                    self.bot.send_message(
                        message.chat.id,
                        "你是第{:d}起床的{}".format(
                            index+1, self._who(message.from_user))
                    )

@@ -2968,32 +2968,33 @@
 %E6%B2%A1%E4%BA%BA%E8%B5%B7%E5%BA%8A')%0A%0A        
+#
 @self.bot.messag
@@ -4983,32 +4983,83 @@
 # Send response%0A
+            if message.chat.type == 'private':%0A    
             if r
@@ -5066,16 +5066,20 @@
 ewaken:%0A
+    
         
@@ -5146,38 +5146,46 @@
 ?%22)%0A            
+   
+ 
 else:%0A
+    
                 
@@ -5199,16 +5199,20 @@
 x == 0:%0A
+    
         
@@ -5274,38 +5274,46 @@
                 
+  
+  
 else:%0A
+    
                 
@@ -5355,32 +5355,36 @@
                 
+    
 message.chat.id,
@@ -5408,16 +5408,20 @@
         
+ 
+   
 %22%E4%BD%A0%E6%98%AF%E7%AC%AC%7B:d%7D
@@ -5427,32 +5427,36 @@
 %7D%E8%B5%B7%E5%BA%8A%E7%9A%84%7B%7D%22.format(%0A
+    
                 
@@ -5506,16 +5506,20 @@
 _user))%0A
+    
         

disable /wan and only reply when message come from private chat