#!/usr/bin/env python3
# This file is placed in the Public Domain.
#
# pylint: disable=C,R,W0105,W0201,W0212,W0613,E0402,E0611,W0718
# ruff: noqa: E402


"24/7 feed fetcher"


import base64
import os
import pwd
import sys
import time


from rssbot.default import Default
from rssbot.objects import Object, edit, fmt, keys, update
from rssbot.persist import Workdir, find, fntime, last, laps, sync
from rssbot.handler import Client, Event
from rssbot.runtime import Errors, init, parse_cmd


from rssbot.modules.irc import Config
from rssbot.modules.rss import Rss


from rssbot import modules as mods


"defines"


Cfg         = Default()
Cfg.mod     = "cmd,mod"
Cfg.name    = "rssbot"
Cfg.version = "540"
Cfg.wd      = os.path.expanduser(f"~/.{Cfg.name}")
Cfg.pidfile = os.path.join(Cfg.wd, f"{Cfg.name}.pid")
Workdir.wd = Cfg.wd


"classes"


class Command:

    cmds = Object()

    @staticmethod
    def add(func):
        setattr(Command.cmds, func.__name__, func)

    @staticmethod
    def command(evt):
        parse_cmd(evt)
        func = getattr(Command.cmds, evt.cmd, None)
        if func:
            try:
                func(evt)
            except Exception as exc:
                Errors.add(exc)
        evt.ready()


class CLI(Client):

    def __init__(self):
        Client.__init__(self)
        self.register("command", Command.command)

    def say(self, channel, txt):
        txt = txt.encode('utf-8', 'replace').decode()
        print(txt)


"commands"


def cfg(event):
    config = Config()
    path = last(config)
    if not event.sets:
        event.reply(
                    fmt(
                        config,
                        keys(config),
                        skip='control,password,realname,sleep,username'.split(",")
                       )
                   )
    else:
        edit(config, event.sets)
        sync(config, path)
        event.reply('ok')


Command.add(cfg)

def cmd(event):
    event.reply(",".join(sorted(list(Command.cmds))))


Command.add(cmd)


def dpl(event):
    if len(event.args) < 2:
        event.reply('dpl <stringinurl> <item1,item2>')
        return
    setter = {'display_list': event.args[1]}
    for _fn, feed in find('rss', {'rss': event.args[0]}):
        if feed:
            update(feed, setter)
            sync(feed)
    event.reply('ok')


Command.add(dpl)


def mre(event):
    if not event.channel:
        event.reply('channel is not set.')
        return
    bot = Broker.get(event.orig)
    if 'cache' not in dir(bot):
        event.reply('bot is missing cache')
        return
    if event.channel not in bot.cache:
        event.reply(f'no output in {event.channel} cache.')
        return
    for _x in range(3):
        txt = bot.gettxt(event.channel)
        if txt:
            bot.say(event.channel, txt)
    size = bot.size(event.channel)
    event.reply(f'{size} more in cache')


Command.add(mre)


def nme(event):
    if len(event.args) != 2:
        event.reply('nme <stringinurl> <name>')
        return
    selector = {'rss': event.args[0]}
    for fnm, feed in find('rss', selector):
        if feed:
            feed.name = event.args[1]
            sync(feed)
    event.reply('ok')


Command.add(nme)


def pwd(event):
    if len(event.args) != 2:
        event.reply('pwd <nick> <password>')
        return
    arg1 = event.args[0]
    arg2 = event.args[1]
    txt = f'\x00{arg1}\x00{arg2}'
    enc = txt.encode('ascii')
    base = base64.b64encode(enc)
    dcd = base.decode('ascii')
    event.reply(dcd)


Command.add(pwd)


def rem(event):
    if len(event.args) != 1:
        event.reply('rem <stringinurl>')
        return
    selector = {'rss': event.args[0]}
    for fnm, feed in find('rss', selector):
        if feed:
            feed.__deleted__ = True
            sync(feed, fnm)
    event.reply('ok')


Command.add(rem)


def res(event):
    if len(event.args) != 1:
        event.reply('res <stringinurl>')
        return
    selector = {'rss': event.args[0]}
    for fnm, feed in find('rss', selector, deleted=True):
        if feed:
            feed.__deleted__ = False
            sync(feed, fnm)
    event.reply('ok')


Command.add(res)


def rss(event):
    if not event.rest:
        nrs = 0
        for fnm, feed in find('rss'):
            nrs += 1
            elp = laps(time.time()-fntime(fnm))
            txt = fmt(feed)
            event.reply(f'{nrs} {txt} {elp}')
        if not nrs:
            event.reply('no rss feed found.')
        return
    url = event.args[0]
    if 'http' not in url:
        event.reply('i need an url')
        return
    for fnm, result in find('rss', {'rss': url}):
        if result:
            event.reply(f'already got {url}')
            return
    feed = Rss()
    feed.rss = event.args[0]
    sync(feed)
    event.reply('ok')


Command.add(rss)


"utilities"


def cmnd(txt, out):
    clt = CLI()
    evn = Event()
    evn.orig = object.__repr__(clt)
    evn.txt = txt
    Command.command(evn)
    for txt in evn.result:
        print(txt)
    evn.wait()
    return evn


"runtime"


def main():
    Errors.enable(print)
    Workdir.skel()
    parse_cmd(Cfg, " ".join(sys.argv[1:]))
    Cfg.mod = ",".join(mods.__dir__())
    return cmnd(Cfg.otxt, print)


if __name__ == "__main__":
    main()
