package com.beem.project.beem.service;

import java.util.ArrayList;
import java.util.List;

import org.jivesoftware.smack.PrivacyList;
import org.jivesoftware.smack.PrivacyListListener;
import org.jivesoftware.smack.PrivacyListManager;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.PrivacyItem;
import org.jivesoftware.smack.packet.PrivacyItem.PrivacyRule;

import android.os.RemoteException;
import android.util.Log;

import com.beem.project.beem.service.aidl.IPrivacyListManager;

/**
 * Privacy list manager in beem.
 * @author nikita
 */
public class PrivacyListManagerAdapter extends IPrivacyListManager.Stub {

    /**
     * Tag.
     */
    public static final String TAG = "PrivacyListManagerAdapter";
    /**
     * default privacy list name.
     */
    public static final String DEFAULT_PRIVACYLIST = "BEEM_DEFAULT_PRIVACY_LIST";

    private PrivacyListManager mAdaptee;
    private List<String> mBlockedUsers = new ArrayList<String>();
    private final XMPPConnection mConnection;
    private final MyPrivacyListListener mPrivacyPacketListener = new MyPrivacyListListener();

    /**
     * Privacy list constructor.
     * @param connection xmppconnection used.
     */
    public PrivacyListManagerAdapter(final XMPPConnection connection) {
	mConnection = connection;
	mAdaptee = PrivacyListManager.getInstanceFor(mConnection);
	mAdaptee.addListener(mPrivacyPacketListener);
    }

    /**
     * Return the blocked user list.
     * @return blocked user list
     * @throws RemoteException
     */
    public List<String> getBlockedUsers() {
	return mBlockedUsers;
    }

    /**
     * Add a user to the blocked user list.
     * @param jid blocked user jid TODO: Ne bloque pas uniquement un utilisateur, fonction a d�couper/revoir
     */
    public synchronized void addBlockedUser(final String jid) {
	Log.d(TAG, "BEGIN addBlockedUser.");
	if (mAdaptee == null) {
	    mAdaptee = PrivacyListManager.getInstanceFor(mConnection);
	    mAdaptee.addListener(mPrivacyPacketListener);
	}
	List<PrivacyItem> pItemList = new ArrayList<PrivacyItem>();
	PrivacyItem pItem = new PrivacyItem(PrivacyItem.Type.jid.name(), true, 1);
	pItem.setFilterMessage(true);
	pItem.setValue(jid);
	pItemList.add(pItem);

	pItem = new PrivacyItem(PrivacyItem.Type.subscription.name(), true, 2);
	pItem.setValue(PrivacyRule.SUBSCRIPTION_BOTH);
	pItemList.add(pItem);

	try {
	    if (mAdaptee.getPrivacyList(DEFAULT_PRIVACYLIST) == null) {
		mAdaptee.createPrivacyList(DEFAULT_PRIVACYLIST, pItemList);
	    }
	} catch (XMPPException e) {
	    Log.e(TAG, e.getMessage());
	} catch (ClassCastException e) {
	    Log.e(TAG, e.getMessage());
	    try {
		mAdaptee.createPrivacyList(DEFAULT_PRIVACYLIST, pItemList);
	    } catch (XMPPException e1) {
		Log.e(TAG, e1.getMessage());
	    }
	}
	try {
	    mAdaptee.setActiveListName(DEFAULT_PRIVACYLIST);
	    mAdaptee.setDefaultListName(DEFAULT_PRIVACYLIST);
	} catch (XMPPException e) {
	    Log.e(TAG, e.getMessage());
	}
	Log.d(TAG, "END addBlockedUser.");
    }

    /**
     * Return a list of users blocked for a specified list.
     * @param listName The list name that will be checked for blocked users.
     * @return A list of String which contains a user JID who is blocked by the user.
     * @throws RemoteException If a Binder remote-invocation error occurred.
     */
    @Override
    public List<String> getBlockedUsersByList(String listName) throws RemoteException {
	List<String> blockedUsersList = new ArrayList<String>();
	try {
	    PrivacyList pList = mAdaptee.getPrivacyList(listName);
	    for (PrivacyItem p : pList.getItems()) {
		if (p.getType().equals(PrivacyItem.Type.jid) && !p.isAllow()) {
		    blockedUsersList.add(p.getValue());
		}
	    }
	} catch (XMPPException e) {
	    Log.e(TAG, e.getMessage());
	}
	return blockedUsersList;
    }

    /**
     * Return the user's PrivacyListManager.
     * @return the current PrivacyListManager instance
     */
    public PrivacyListManager getManager() {
	return mAdaptee;
    }

    /**
     * A class which allows listening on a PrivacyList TODO: Besoin d'en discuter. Va t-on g�rer plusieurs listes ? Une
     * seule ?
     */
    class MyPrivacyListListener implements PrivacyListListener {
	/**
	 * constructor.
	 */
	public MyPrivacyListListener() {
	}

	@Override
	public void setPrivacyList(String listName, List<PrivacyItem> listItem) {
	    Log.d(TAG, "BEGIN setPrivacyList.");
	    try {
		if (mAdaptee.getPrivacyList(listName) == null)
		    mAdaptee.createPrivacyList(listName, listItem);
		else
		    mAdaptee.updatePrivacyList(listName, listItem);
	    } catch (XMPPException e) {
		Log.e(TAG, e.getMessage());
	    }
	    Log.d(TAG, "END setPrivacyList.");
	}

	@Override
	public void updatedPrivacyList(String listName) {
	    Log.d(TAG, "BEGIN updatedPrivacyList.");
	    if (listName.equals(DEFAULT_PRIVACYLIST)) {
		try {
		    mBlockedUsers = getBlockedUsersByList(DEFAULT_PRIVACYLIST);
		} catch (RemoteException e) {
		    Log.e(TAG, e.getMessage());
		}
	    }
	    Log.d(TAG, "END updatedPrivacyList.");
	}
    }
}
