/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq;
import static edu.tsinghua.lumaqq.qq.QQPort.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import edu.tsinghua.lumaqq.qq.beans.Card;
import edu.tsinghua.lumaqq.qq.beans.ContactInfo;
import edu.tsinghua.lumaqq.qq.beans.FriendRemark;
import edu.tsinghua.lumaqq.qq.beans.Member;
import edu.tsinghua.lumaqq.qq.beans.QQOrganization;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.beans.Signature;
import edu.tsinghua.lumaqq.qq.events.IQQListener;
import edu.tsinghua.lumaqq.qq.events.PacketEvent;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.net.ConnectionPolicyFactory;
import edu.tsinghua.lumaqq.qq.net.IConnection;
import edu.tsinghua.lumaqq.qq.net.IConnectionPolicy;
import edu.tsinghua.lumaqq.qq.net.IConnectionPolicyFactory;
import edu.tsinghua.lumaqq.qq.net.IConnectionPool;
import edu.tsinghua.lumaqq.qq.net.IConnectionPoolFactory;
import edu.tsinghua.lumaqq.qq.packets.ErrorPacket;
import edu.tsinghua.lumaqq.qq.packets.InPacket;
import edu.tsinghua.lumaqq.qq.packets.OutPacket;
import edu.tsinghua.lumaqq.qq.packets.Packet;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AddFriendAuthResponsePacket;
import edu.tsinghua.lumaqq.qq.packets.out.AddFriendExPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AdvancedSearchUserPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AuthorizePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ChangeStatusPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterActivatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterActivateTempPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterAuthPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterCommitMemberOrganizationPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterCommitOrganizationPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterCreatePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterCreateTempPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterDismissPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterExitPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterExitTempPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetCardBatchPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetCardPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetMemberInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetOnlineMemberPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterGetTempInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterJoinPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyCardPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyMemberPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyTempInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterModifyTempMemberPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSearchPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSendIMExPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSendTempIMPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSetRolePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterSubClusterOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterTransferRolePacket;
import edu.tsinghua.lumaqq.qq.packets.out.ClusterUpdateOrganizationPacket;
import edu.tsinghua.lumaqq.qq.packets.out.DeleteFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.DownloadGroupFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.FriendDataOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.FriendLevelOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetFriendListPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetKeyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetLoginTokenPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetOnlineOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GetUserInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.GroupDataOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.KeepAlivePacket;
import edu.tsinghua.lumaqq.qq.packets.out.LoginPacket;
import edu.tsinghua.lumaqq.qq.packets.out.LogoutPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ModifyInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out.PrivacyDataOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.ReceiveIMReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.out.RemoveSelfPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SearchUserPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SendIMPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SendSMSPacket;
import edu.tsinghua.lumaqq.qq.packets.out.SignatureOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.TempSessionOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.UploadGroupFriendPacket;
import edu.tsinghua.lumaqq.qq.packets.out.UserPropertyOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.WeatherOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out._03.GetCustomHeadDataPacket;
import edu.tsinghua.lumaqq.qq.packets.out._03.GetCustomHeadInfoPacket;
import edu.tsinghua.lumaqq.qq.packets.out._05.RequestAgentPacket;
import edu.tsinghua.lumaqq.qq.packets.out._05.RequestBeginPacket;
import edu.tsinghua.lumaqq.qq.packets.out._05.RequestFacePacket;
import edu.tsinghua.lumaqq.qq.packets.out._05.TransferPacket;
import edu.tsinghua.lumaqq.qq.robot.IRobot;
/**
* QQ的客户端类,这个类为用户提供一个方便的接口,比如发送消息之类的,只需要调用一个
* 方法便可以完成了。
*
* LumaQQ网络层通过NIO实现,每个Client分配一个Selector,每个Selector可以监听多个
* Channel,channel包装在IPort的实现类中,对于一个Client,有一个Main Port,这个
* Main Port定义为连接QQ登陆服务器的那个Port。系统登陆之初之有一个Port即Main Port,
* 根据需要可以开启其他Port
*
* @author luma
*/
public class QQClient implements IQQListener {
/**
* 单线程执行器
*/
protected static final SingleExecutor executor = new SingleExecutor();
/** 包处理器数目 */
protected static final int PROCESSOR_COUNT = 4;
// 登陆的服务器IP
private String loginServer;
// TCP方式登录时的服务器端口,UDP方式时无用处
private int tcpLoginPort;
// 包处理器路由器
private ProcessorRouter router;
// QQ监听器
private LinkedList<IQQListener> qqListeners, qqListenersBackup;
// QQ用户
private QQUser user;
// 当前是否正在登陆
private boolean logging;
// 当前是否在重定向登录
private boolean loginRedirect;
// 网络连接池
private IConnectionPool pool;
// 网络连接池工厂
private IConnectionPoolFactory poolFactory;
// 连接策略工厂
private IConnectionPolicyFactory policyFactory;
// 代理类型
private int proxyType;
// 代理服务器地址