#!/usr/bin/python
# -*- coding: utf-8 -*-

# --------------------------------------------------------------------------- #
#                                                                             #
#    Plugin for iSida Jabber Bot                                              #
#    Clients statistics                                                       #
#    Copyright (C) diSabler <dsy@dsy.name>                                    #
#                                                                             #
#    This program is free software: you can redistribute it and/or modify     #
#    it under the terms of the GNU General Public License as published by     #
#    the Free Software Foundation, either version 3 of the License, or        #
#    (at your option) any later version.                                      #
#                                                                             #
#    This program is distributed in the hope that it will be useful,          #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
#    GNU General Public License for more details.                             #
#                                                                             #
#    You should have received a copy of the GNU General Public License        #
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
#                                                                             #
# --------------------------------------------------------------------------- #

def clients_stats(type, jid, nick, text):
    text = text.lower().split()
    match = '%'
    is_short = 'short' in text
    is_os = 'os' in text
    is_user = 'user' in text
    is_global = 'global' in text or 'total' in text or 'all' in text

    # Удаляем флаги
    for flag in ['all', 'total', 'global', 'short', 'os', 'user']:
        while flag in text:
            text.remove(flag)

    # Если есть текст для поиска
    if text:
        match = '%%%s%%' % ' '.join(text)

    # Если указан пользователь
    target_nick = None
    if is_user and text:
        # Ищем ник в комнате
        room_nicks = [t[1] for t in megabase if t[0] == jid]
        for word in text:
            if word in room_nicks:
                target_nick = word
                match = '%%%s%%' % ' '.join([t for t in text if t != word])
                break
    if is_user and not target_nick:
        target_nick = nick

    # Если указан пользователь, получаем его JID
    if is_user and target_nick:
        cjid = getRoom(get_level(jid, target_nick)[1])
        if cjid == 'None':
            send_msg(type, jid, nick, L('User %s not found in room.', '%s/%s' % (jid, nick)) % target_nick)
            return
    else:
        cjid = None

    # Строим запрос
    if is_user and cjid:
        req = 'SELECT client, version, os FROM versions WHERE jid=%s'
        params = (cjid,)
    elif is_global:
        req = 'SELECT client, version, os FROM versions WHERE client ilike %s OR version ilike %s OR os ilike %s'
        params = (match, match, match)
    else:
        req = 'SELECT client, version, os FROM versions WHERE room=%s AND (client ilike %s OR version ilike %s OR os ilike %s)'
        params = (jid, match, match, match)

    st = cur_execute_fetchall(req, params)

    if not st:
        send_msg(type, jid, nick, L('No client data available. Try later.', '%s/%s' % (jid, nick)))
        return

    # Группируем
    stats = {}
    for row in st:
        if is_os:
            key = row[2]  # OS
            if key and is_short:
                if '/' in key:
                    key = key.split('/')[0]
                elif key.lower().startswith('microsoft') or key.startswith('(c)') or key.startswith('©'):
                    key = key.split()[1] if len(key.split()) > 1 else key
                elif '=' in key:
                    key = key.split('=')[1]
                key = key.split()[0] if key else 'Unknown'
        else:
            if is_short:
                key = row[0]  # только имя клиента
            else:
                key = '%s %s' % (row[0], row[1])  # клиент + версия

        if not key or key == 'None':
            key = 'Unknown'

        stats[key] = stats.get(key, 0) + 1

    # Сортируем
    sorted_stats = sorted(stats.items(), key=lambda x: x[1], reverse=True)

    # Формируем сообщение
    if is_user:
        if is_short:
            msg = L('Client stats for %s: %s', '%s/%s' % (jid, nick)) % (
                target_nick, ', '.join(['%s (%s)' % (k, v) for k, v in sorted_stats[:10]])
            )
        else:
            msg = L('Client stats for %s:\n%s', '%s/%s' % (jid, nick)) % (
                target_nick, '\n'.join(['%s' % k for k, v in sorted_stats])
            )
    else:
        lines = []
        for i, (k, v) in enumerate(sorted_stats[:10], 1):
            lines.append('%s. %s - %s' % (i, k, v))
        msg = L('Client stats:\n%s', '%s/%s' % (jid, nick)) % '\n'.join(lines)

    send_msg(type, jid, nick, msg)

def clients_help(type, jid, nick, text):
    help_text = L("""
clients [global|total|all] [short] [os] [user] [filter]

Параметры:
  global/total/all — глобальная статистика по всем комнатам
  short — краткий вывод (только имя клиента или ОС)
  os — группировка по операционной системе
  user <nick> — статистика для конкретного пользователя
  filter — текст для фильтрации

Примеры:
  .clients                         — статистика в текущей комнате
  .clients global                  — глобальная статистика
  .clients short                   — краткий вывод
  .clients os                      — по ОС
  .clients user <nick>             — статистика для указанного пользователя
  .clients global short os         — глобально, кратко, по ОС
  .clients Windows                 — фильтр по Windows
""", '%s/%s' % (jid, nick))
    send_msg(type, jid, nick, help_text)

def clients_version_cb(room, jid, nick, is_answ):
    # Результат jabber:iq:version уже сохранён ядром в таблицу versions
    return None

def clients_collect(room, jid, nick, type, mass):
    # Автоматически запрашиваем версию клиента при входе пользователя в комнату,
    # чтобы наполнить таблицу versions данными для команды "clients".
    global iq_request
    if type == 'unavailable' or jid == 'None':
        return
    if getRoom(jid) == getRoom(Settings['jid']):
        return
    # mass[7] - not_found из ядра: 0 при входе нового пользователя,
    # 1/2 при обновлении presence уже присутствующего участника
    if not (not mass[7] or is_start):
        return
    who = '%s/%s' % (room, nick)
    iqid = get_id()
    i = xmpp.Node('iq', {'id': iqid, 'type': 'get', 'to': who}, payload = [xmpp.Node('query', {'xmlns': xmpp.NS_VERSION},[])])
    iq_request[iqid] = (time.time(), clients_version_cb, [room, jid, nick], xmpp.NS_VERSION)
    pprint('*** Clients version request for %s/%s' % (room,nick),'cyan')
    sender(i)

global execute, presence_control

presence_control = [clients_collect]

execute = [
    (4, 'clients', clients_stats, 2, 'clients [global|short|os|user <nick>|filter] — show client statistics'),
    (4, 'clients_help', clients_help, 2, 'Show help for clients command'),
]
