package org.freecode.irc.votebot;

import org.freecode.irc.*;
import org.freecode.irc.event.CtcpRequestListener;
import org.freecode.irc.event.NumericListener;
import org.freecode.irc.event.PrivateMessageListener;
import org.freecode.irc.votebot.api.FVBModule;
import org.freecode.irc.votebot.dao.PollDAO;
import org.freecode.irc.votebot.dao.VoteDAO;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: Shivam
 * Date: 17/06/13
 * Time: 00:05
 */
public class FreeVoteBot implements PrivateMessageListener {
    public static final double VERSION = 1.065D;
    public static final String CHANNEL_SOURCE = "#freecode";

    private PollDAO pollDAO;
    private VoteDAO voteDAO;
    private String[] channels;
    private String nick, realName, serverHost, user;
    private int port;

    private IrcConnection connection;

    private ExpiryQueue<String> expiryQueue = new ExpiryQueue<>(1500L);
    private LinkedList<FVBModule> moduleList = new LinkedList<>();
    public static final SimpleDateFormat SDF;


    static {
        SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.UK);
        SDF.setTimeZone(TimeZone.getTimeZone("Europe/London"));
    }

    public void init() {
        connectToIRCServer();
        NoticeFilter.setFilterQueue(connection, 5000L);
        addNickInUseListener();
        registerUser();
        addCTCPRequestListener();
        identifyToNickServ();
        joinChannels();
    }

    private void registerUser() {
        try {
            connection.register(nick, user, realName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        connection.addListener(this);
    }

    private void addNickInUseListener() {
        NumericListener nickInUse = new NumericListener() {
            public int getNumeric() {
                return IrcConnection.ERR_NICKNAMEINUSE;
            }

            public void execute(String rawLine) {
                FreeVoteBot.this.nick = FreeVoteBot.this.nick + "_";
                try {
                    connection.sendRaw("NICK " + FreeVoteBot.this.nick);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        connection.addListener(nickInUse);
    }

    private void addCTCPRequestListener() {
        connection.addListener(new CtcpRequestListener() {
            public void onCtcpRequest(CtcpRequest request) {
                if (request.getCommand().equals("VERSION")) {
                    request.getIrcConnection().send(new CtcpResponse(request.getIrcConnection(),
                            request.getNick(), "VERSION", "FreeVoteBot " + VERSION + " by " + CHANNEL_SOURCE + " on irc.rizon.net"));
                } else if (request.getCommand().equals("PING")) {
                    request.getIrcConnection().send(new CtcpResponse(request.getIrcConnection(),
                            request.getNick(), "PING", request.getArguments()));
                }
            }
        });
    }

    private void connectToIRCServer() {
        try {
            connection = new IrcConnection(serverHost, port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void identifyToNickServ() {
        File pass = new File("password.txt");
        if (pass.exists()) {
            try {
                BufferedReader read = new BufferedReader(new FileReader(pass));
                String s = read.readLine();
                if (s != null) {
                    connection.send(new Privmsg("NickServ", "identify " + s, connection));
                }
                read.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void joinChannels() {
        for (String channel : channels) {
            connection.joinChannel(channel);
        }
    }


    public void onPrivmsg(final Privmsg privmsg) {
        try {
            if (privmsg.getNick().equalsIgnoreCase(nick)) {
                return;
            }

            String sender = privmsg.getNick().toLowerCase();
            if (expiryQueue.contains(sender)) {
                return;
            } else {
                expiryQueue.insert(sender);
            }

            for (FVBModule module : moduleList) {
                if (module.isEnabled() && module.canRun(privmsg)) {
                    module.process(privmsg);
                    return;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void askChanServForUserCreds(Privmsg privmsg) {
        privmsg.getIrcConnection().send(new Privmsg("ChanServ", "WHY " + FreeVoteBot.CHANNEL_SOURCE + " " + privmsg.getNick(), privmsg.getIrcConnection()));
    }

    public void setPollDAO(PollDAO pollDAO) {
        this.pollDAO = pollDAO;
    }

    public void setVoteDAO(VoteDAO voteDAO) {
        this.voteDAO = voteDAO;
    }

    public void setNick(String nick) {
        this.nick = nick;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public void setServerHost(String serverHost) {
        this.serverHost = serverHost;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public void setPort(String port) {
        this.port = Integer.parseInt(port);
    }

    public void setChannels(String channels) {
        this.channels = channels.split(",");
    }

    public void setModules(final FVBModule[] modules) {
        moduleList.clear();
        moduleList.addAll(Arrays.asList(modules));
    }
}

@@ -52,17 +52,137 @@
 ode.irc.
-*
+CtcpRequest;%0Aimport org.freecode.irc.CtcpResponse;%0Aimport org.freecode.irc.IrcConnection;%0Aimport org.freecode.irc.Privmsg
 ;%0Aimport
@@ -576,38 +576,8 @@
 on;%0A
-import java.sql.SQLException;%0A
 impo
@@ -716,72 +716,8 @@
 one;
-%0Aimport java.util.regex.Matcher;%0Aimport java.util.regex.Pattern;
 %0A%0A/*
@@ -880,10 +880,9 @@
  1.0
-65
+7
 D;%0A 

Update version