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

"""
    This file is part of Pynder.

    Pynder 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.

    Pynder 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 Pynder.  If not, see <http://www.gnu.org/licenses/>.
"""

import datetime
from operator import itemgetter
import os
import re

import bot
import config
import feedparser
import utils
import version

__author__ = "Strubbl"
__version__ = version.version
__credits__ = ["Strubbl"]

class Pynder(bot.Bot):
    """
    class that extends the Bot class in order to add commands to the bot
    """

    def __init__(self, name, jid, password, resource=None):
        """
        init method to set up a Bot and an empty dict to keep the slapped things
        """
        super(Pynder, self).__init__(name, jid, password, resource)
        self.slapped = {}


    def cmd_echo(self, args, tojid, typ="chat"):
        """
        echo command to simply echo something as text
        """
        self.send(self.room_name, args)

    def cmd_help(self, args, tojid, typ="chat"):
        """
        help command

        returns all availabe commands of this bot class
        """
        helptext = "available commands: " + str(self.commands)
        self.send(tojid, helptext, typ)


    def cmd_uptime(self, args, tojid, typ="chat"):
        """
        calculates, formats it human readable and then echos the uptime
        """
        uptime = datetime.datetime.today()-self.birthday
        # python >= 2.7: http://docs.python.org/library/datetime.html#datetime.timedelta.total_seconds
        #uptimestr = utils.format_seconds(uptime.total_seconds())
        # for compatibility with python < 2.7
        uptimestr = utils.format_seconds((uptime.microseconds + (uptime.seconds + uptime.days * 24 * 3600) * 10 ** 6) / 10 ** 6)
        self.send(tojid, uptimestr, typ)


    def cmd_slap(self, args, tojid, typ="chat"):
        """
        slaps anything you want and increases the counter counting how many times it was slapped
        """
        key = args.lower()
        if key in self.slapped:
            self.slapped[key] += 1
        else:
            self.slapped[key] = 1
        self.send(tojid, "/me slaps " + args, typ)
#        self.send(tojid, "/me slaps " + args + ". (" + str(self.slapped[key]) + " totally slapped)", typ)

    def cmd_totallyslapped(self, args, tojid, typ="chat"):
        """
        echo what and how often it was slapped sorted by number of slaps
        """
        #sort the dict by value
        pairs = sorted(self.slapped.iteritems(), key=itemgetter(1), reverse=True)

        i = 1
        message = ""
        for key, value in pairs:
            if i > 1:
                message += "\n"
            message += str(i) + "# " + key + ": " + str(value)
            i += 1

        self.send(tojid, message, typ)

    def cmd_totalusers(self, args, tojid, typ="chat"):
        """
        Minecraft: echo how many users are ingame
        """
        netstatout = os.popen("/bin/netstat -tn").read()
        searchstring = config.mcport + ".*" + config.established
        connlist =  re.findall(searchstring,netstatout)
        usercount = str(len(connlist))
        message=  "user online: " + usercount
        self.send(tojid,message,typ)

    def cmd_listusers(self, args, tojid, typ="chat"):
        """
        Minecraft: echo list of users
        """
        os.popen("screen -S mc -X stuff 'list^M'")
        time.sleep(0.1)
        logcommand = "/usr/bin/tail -n 1 "+ config.watch_file
        logoutput = os.popen(logcommand).read()
        pos = re.search(r'(]:) (.*$)',logoutput)
        message = pos.group(2)
        self.send(tojid,message,typ)

    def cronjob(self):
        self.check_rss()

    def check_rss(self):
        rss_cache_dir = config.cache_dir + os.sep + "rss"
        newest_item_written = False
        if config.rss_feeds:
            self.rootlog.debug("rss feeds found:" + str(config.rss_feeds))
            for name, feed in config.rss_feeds.items():
                last_cache_item = utils.read_file(rss_cache_dir + os.sep + name)
                f = feedparser.parse(feed)
                self.rootlog.debug(str(f["channel"]["title"] + " feed fetched"))
                if last_cache_item != None:
                    self.rootlog.debug("last_cache_item not None: " + last_cache_item)
                    for i in f["items"]:
                        if str(last_cache_item.strip()) == str(i["date"].strip()):
                            self.rootlog.debug("item found, aborting")
                            break
                        else:
                            if newest_item_written == False:
                                utils.write_file(rss_cache_dir + os.sep + name, i["date"].strip())
                                newest_item_written = True
                            # write date of this feed into file (not elegant)
                            text2chat = "".join(["[", name, "] ", i["title"], " ", i["link"]])
                            self.rootlog.debug(text2chat)
                            self.send(self.room_name, text2chat)
                else:
                    self.rootlog.debug("last_cache_item is None")
                    utils.write_file(rss_cache_dir + os.sep + name, f["items"][0]["date"])

    def parse_minecraft_log(self, line):
        # ^\[[\d:]+\] \[.*\]: <(\S+)> (.*)$
        p = re.compile('^\[[\d:]+\] \[.*\]: <(\S+)> (.*)$')
        m = p.match(line)
        if m != None:
            who = m.group(1)
            msg = m.group(2)
            self.send(self.room_name, who + ": " + msg)

    def parse_new_file_content(self, line):
        self.parse_minecraft_log(line)

    def write_to_minecraft_chat(self, message):
        self.rootlog.debug("write_to_minecraft_chat: orig message: " + message)
        message = message.replace(config.room + "@" + config.conference_server + "/", "")
        message = re.escape(message)
        for i in ".,:-()[]$€?! äüöÄÖÜß":
            message = message.replace("\\" + i, i)
        message = message.replace("\n", " ")
        self.rootlog.debug("write_to_minecraft_chat: message: " + message)
        minecraft_say = config.minecraft_say.replace('%message%', message)
        self.rootlog.debug("write_to_minecraft_chat: command: " + minecraft_say)
        os.system(minecraft_say)

    def handle_message(self, nick, text):
        message = nick + ": " + text
        self.write_to_minecraft_chat(message)


### main program
if __name__ == "__main__":
    p = Pynder(config.name, config.jid, config.password, config.resource)
    p.go_online()

