package me.rkfg.xmpp.bot.plugins;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;

import me.rkfg.xmpp.bot.Main;
import me.rkfg.xmpp.bot.domain.Karma;
import me.rkfg.xmpp.bot.domain.KarmaHistory;
import me.rkfg.xmpp.bot.nxt.NXTAPI;
import me.rkfg.xmpp.bot.nxt.Transaction;

import org.hibernate.Session;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.muc.Occupant;

import ru.ppsrk.gwt.client.ClientAuthException;
import ru.ppsrk.gwt.client.LogicException;
import ru.ppsrk.gwt.server.HibernateCallback;
import ru.ppsrk.gwt.server.HibernateUtil;
import ru.ppsrk.gwt.server.SettingsManager;

public class KarmaPlugin extends CommandPlugin {

    private NXTAPI nxtapi;
    private String karmaAddress;

    @Override
    public void init() {
        SettingsManager settingsManager = Main.getSettingsManager();
        karmaAddress = settingsManager.getStringSetting("karmaAddress");
        nxtapi = new NXTAPI(settingsManager.getStringSetting("nxtAPIAddress"), karmaAddress, settingsManager.getStringSetting("karmaPass"));
        new Timer("karma timer", true).schedule(new TimerTask() {

            @Override
            public void run() {
                try {
                    HibernateUtil.exec(new HibernateCallback<Void>() {

                        @Override
                        public Void run(Session session) throws LogicException, ClientAuthException {
                            KarmaHistory karmaHistory = (KarmaHistory) session
                                    .createQuery("from KarmaHistory kh order by kh.blockTimestamp desc").setMaxResults(1).uniqueResult();
                            Long since = 0L;
                            if (karmaHistory != null) {
                                since = karmaHistory.getBlockTimestamp() + 1;
                            }
                            List<Transaction> transactions = nxtapi.getTransactionsSince(since, 1L);
                            for (Transaction transaction : transactions) {
                                log.info("Processing tx: " + transaction);
                                String jid = nxtapi.getMessage(transaction.getTxid()).toLowerCase();
                                if (jid.length() > 1) {
                                    boolean add = true;
                                    if (jid.charAt(0) == '-') {
                                        add = false;
                                        jid = jid.substring(1);
                                    }
                                    if (jid.charAt(0) == '+') {
                                        jid = jid.substring(1);
                                    }
                                    if (jid.contains("@") && jid.contains(".") && !jid.contains(" ")) {
                                        Karma karma = (Karma) session.createQuery("from Karma k where k.jid = :jid").setString("jid", jid)
                                                .uniqueResult();
                                        if (karma == null) {
                                            karma = (Karma) session.merge(new Karma(jid));
                                        }
                                        Long change = transaction.getAmount() * (add ? 1 : -1);
                                        session.merge(new KarmaHistory(new Date(), transaction.getTimestamp(), karma, change));
                                        karma.setKarma(karma.getKarma() + change);
                                    }
                                }
                            }
                            return null;
                        }
                    });
                } catch (LogicException | ClientAuthException e) {
                    e.printStackTrace();
                }
            }
        }, 10000, 10000);
    }

    @Override
    public String processCommand(final Message message, final Matcher matcher) throws LogicException, ClientAuthException {
        return HibernateUtil.exec(new HibernateCallback<String>() {

            @SuppressWarnings("unchecked")
            @Override
            public String run(Session session) throws LogicException, ClientAuthException {
                List<Karma> karmas;
                String byJID = matcher.group(COMMAND_GROUP);
                if (byJID != null) {
                    karmas = session.createQuery("from Karma k where k.jid like :jid").setString("jid", byJID + "%").list();
                } else {
                    karmas = session.createQuery("from Karma k order by k.karma").list();
                }
                StringBuilder sb = new StringBuilder("Карма участников:\n");
                Map<String, Occupant> occupants = Main.getMUCManager().listMUCOccupantsByJID(getBareAddress(message));
                for (Karma karma : karmas) {
                    String name = karma.getJid();
                    Occupant jidOccupant = occupants.get(name);
                    if (jidOccupant != null) {
                        name += " (aka " + jidOccupant.getNick() + ")";
                    }
                    sb.append(name + ": " + karma.getKarma()).append("\n");
                }
                return sb.toString();
            }
        });
    }

    @Override
    public List<String> getCommand() {
        return Arrays.asList("k", "r", "к", "л");
    }

    @Override
    public String getManual() {
        return "посмотреть карму участников.\n" + "Формат: [начало JID'а участника]\n"
                + "Если не указывать JID, выводятся все известные аккаунты с кармой.\n"
                + "Для изменения кармы отправьте X NXT (где X — целое) на адрес " + karmaAddress
                + ", к платежу приложите сообщение с JID, для которого хотите увеличить карму на X пунктов. "
                + "Для уменьшения кармы поставьте вплотную перед JID знак минуса.\n" + "Пример: " + PREFIX + "k admin";
    }
}

@@ -2465,24 +2465,24 @@
 jid.
-charAt(0) == '-'
+startsWith(%22- %22)
 ) %7B%0A
@@ -2586,33 +2586,33 @@
 = jid.substring(
-1
+2
 );%0A             
@@ -2684,24 +2684,24 @@
 jid.
-charAt(0) == '+'
+startsWith(%22+ %22)
 ) %7B%0A
@@ -2760,17 +2760,17 @@
 bstring(
-1
+2
 );%0A     
@@ -5986,17 +5986,8 @@
 %D1%8C%D1%82%D0%B5 
-%D0%B2%D0%BF%D0%BB%D0%BE%D1%82%D0%BD%D1%83%D1%8E 
 %D0%BF%D0%B5%D1%80%D0%B5
@@ -6003,16 +6003,60 @@
 %D0%BA %D0%BC%D0%B8%D0%BD%D1%83%D1%81%D0%B0
+ %D1%87%D0%B5%D1%80%D0%B5%D0%B7 %D0%BF%D1%80%D0%BE%D0%B1%D0%B5%D0%BB (%D0%BD%D0%B0%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80: - admin@domain.com)
 .%5Cn%22 + %22
@@ -6064,16 +6064,32 @@
 %D1%80%D0%B8%D0%BC%D0%B5%D1%80: %22
+%0A               
  + PREFI

Fix add/subtract message rules.