#!/usr/bin/env python3

import logging as log
import time

from cardDB import CardDB
from constants import Constants
from helper import HSHelper
from praww import RedditBot
import commentDB
import credentials
import formatter


# answer pms of the same user only every x seconds
PM_RATE_LIMIT = 60


def answerComment(r, comment, answeredDB, helper):
    """read and answer a comment"""

    cards, answer = helper.parseText(comment.body)

    if cards and answer:
        if answeredDB.exists(comment.parent_id, cards):
            # send pm instead of comment reply
            sub = comment.submission

            log.info("sending duplicate msg: %s with %s",
                    comment.author, cards)
            header = formatter.createDuplicateMsg(sub.title, sub.permalink)
            message = header + answer

            r.redditor(comment.author.name) \
                    .message('You requested cards in a comment', message)
        else:
            # reply to comment
            log.info("replying to comment: %s %s with %s",
                    comment.id, comment.author.name, cards)
            comment.reply(answer)


def answerMention(r, comment, answeredDB, helper):
    """read and answer a mention"""

    cards, answer = helper.parseText(comment.body)

    if cards and answer:
        if not answeredDB.exists(comment.parent_id, cards):
            # reply to comment
            log.info("replying to comment: %s %s with %s",
                    comment.id, comment.author.name, cards)
            comment.reply(answer)
    else:
        log.debug("forwarded mention with id: %s", comment.id)
        # forward mentions without cards to admin
        subject = '${} /u/{} in /r/{}/ "{}"'.format(comment.id, comment.author,
                comment.subreddit, comment.submission.title)
        r.redditor(credentials.admin_username).message(subject, comment.body)


def answerSubmission(submission, helper):
    """read and answer a submission"""

    text = submission.title

    if submission.is_self:
        text += ' ' + submission.selftext

    cards, answer = helper.parseText(text)

    if cards and answer:
        log.info("replying to submission: %s %s with %s",
                submission.id, submission.author.name, cards)
        submission.reply(answer)


def answerPM(r, msg, pmUserCache, helper):
    """ read and answer a pm """

    subject_author = ""

    # subreddit mod pm
    if msg.subreddit:
        author = msg.subreddit.display_name
        subject_author += " /r/" + author

    if msg.author:
        author = msg.author.name
        subject_author += " /u/" + author

    log.debug("found message with id: %s from %s", msg.id, author)

    if msg.author and not msg.distinguished and author in pmUserCache:
        log.debug("user %s is in recent msg list", author)
        return

    if author == credentials.admin_username and msg.subject[:5] == 're: #':
        forwardPMAnswer(r, msg)
        return

    if author == credentials.admin_username and msg.subject[:5] == 're: $':
        forwardMentionAnswer(r, msg)
        return

    pmUserCache[author] = int(time.time()) + PM_RATE_LIMIT

    text = msg.subject + ' ' + msg.body
    cards, answer = helper.parseText(text)

    if '[[info]]' in text:
        answer = helper.getInfoText(author) + answer

    if cards or answer:
        log.info("ass sending msg: %s with %s %s", author, cards, answer)
        if cards:
            log.info("sending msg: %s with %s", author, cards)
        msg.reply(answer)
    else:
        # vip tags (mod, admin usw)
        if msg.distinguished:
            subject_author += " [" + msg.distinguished + "]"

        log.debug("forwarded message with id: %s", msg.id)
        # forward messages without cards to admin
        subject = '#{}{}: "{}"'.format(msg.id, subject_author, msg.subject)
        r.redditor(credentials.admin_username).message(subject, msg.body)


def getIdFromSubject(subject):
    first_space = subject.find(' ', 6)
    slice_to = first_space if first_space > 1 else len(subject)
    if slice_to > 5:
        return subject[5:slice_to]


def forwardPMAnswer(r, answer_msg):
    """handle messages from bot admin which are answers to
    forwarded messages
    """
    message_id = getIdFromSubject(answer_msg.subject)

    if message_id:
        old_message = r.inbox.message(message_id)

        if old_message:
            log.debug("forwarded answer to message id: %s", old_message.id)
            old_message.reply(answer_msg.body)
            answer_msg.reply("answer forwarded")


def forwardMentionAnswer(r, answer_msg):
    """handle messages from bot admin which are answers to
    forwarded mentions
    """
    comment_id = getIdFromSubject(answer_msg.subject)

    if comment_id:
        src_comment = r.comment(comment_id)

        if src_comment:
            log.debug("forwarded answer to comment id: %s", src_comment.id)
            src_comment.reply(answer_msg.body)
            answer_msg.reply("answer forwarded")


def cleanPMUserCache(cache):
    """ clean recent user msg cache """

    removeUser = []
    now = int(time.time())

    for user, utime in cache.items():
        if now > utime:
            log.debug("removing author %s from recent list", user)
            removeUser.append(user)

    for ku in removeUser:
        del cache[ku]


def main():
    log.debug('main() hearthscan-bot starting')

    # load constant values
    constants = Constants()
    # init answered comments sqlite DB
    answeredDB = commentDB.DB()
    # load card DB
    url = 'https://raw.githubusercontent.com/d-schmidt/hearthscan-bot/master/data/tempinfo.json'
    cardDB = CardDB(constants=constants, tempJSONUrl=url)
    # init hs helper for hearthstone stuff
    helper = HSHelper(cardDB, constants)
    # pm spam filter cache
    pmUserCache = {}

    def submissionListener(r, submission):
        answerSubmission(submission, helper)

    def commentListener(r, comment):
        answerComment(r, comment, answeredDB, helper)

    def mentionListener(r, comment):
        answerMention(r, comment, answeredDB, helper)

    def pmListener(r, message):
        answerPM(r, message, pmUserCache, helper)

    def postAction():
        cleanPMUserCache(pmUserCache)
        cardDB.refreshTemp()

    try:
        RedditBot(subreddits=credentials.subreddits,
                    newLimit=250,
                    connectAttempts=5,
                    userBlacklist=set(credentials.userBlacklist)) \
                .withSubmissionListener(submissionListener) \
                .withCommentListener(commentListener) \
                .withMentionListener(mentionListener) \
                .withPMListener(pmListener) \
                .run(postAction)
    except:
        log.exception('main() RedditBot failed unexpectedly')
    finally:
        log.warning('main() leaving hearthscan-bot')
        answeredDB.close()


if __name__ == "__main__":
    log.basicConfig(filename="bot.log",
                    format='%(asctime)s %(levelname)s %(module)s:%(name)s %(message)s',
                    level=log.DEBUG)

    log.getLogger('prawcore').setLevel(log.INFO)
    log.getLogger('urllib3.connectionpool').setLevel(log.INFO)

    # start
    try:
        main()
    except:
        log.exception('main() failed unexpectedly')
        exit(1)
@@ -3342,82 +3342,8 @@
 er:%0A
-        log.info(%22ass sending msg: %25s with %25s %25s%22, author, cards, answer)%0A
     

remove verbose log message