package org.apache.catalina.tribes.group.interceptors;

import org.apache.catalina.tribes.group.ChannelInterceptorBase;
import org.apache.catalina.tribes.Member;
import java.util.ArrayList;
import org.apache.catalina.tribes.group.AbsoluteOrder;
import org.apache.catalina.tribes.ChannelException;
import org.apache.catalina.tribes.Channel;

public class StaticMembershipInterceptor
    extends ChannelInterceptorBase {
    protected ArrayList members = new ArrayList();
    protected Member localMember = null;

    public StaticMembershipInterceptor() {
        super();
    }

    public void addStaticMember(Member member) {
        synchronized (members) {
            if (!members.contains(member)) members.add(member);
        }
    }

    public void removeStaticMember(Member member) {
        synchronized (members) {
            if (members.contains(member)) members.remove(member);
        }
    }

    public void setLocalMember(Member member) {
        this.localMember = member;
    }

    /**
     * has members
     */
    public boolean hasMembers() {
        return super.hasMembers() || (members.size()>0);
    }

    /**
     * Get all current cluster members
     * @return all members or empty array
     */
    public Member[] getMembers() {
        if ( members.size() == 0 ) return super.getMembers();
        else {
            synchronized (members) {
                Member[] others = super.getMembers();
                Member[] result = new Member[members.size() + others.length];
                for (int i = 0; i < others.length; i++) result[i] = others[i];
                for (int i = 0; i < members.size(); i++) result[i + others.length] = (Member) members.get(i);
                AbsoluteOrder.absoluteOrder(result);
                return result;
            }//sync
        }//end if
    }

    /**
     *
     * @param mbr Member
     * @return Member
     */
    public Member getMember(Member mbr) {
        if ( members.contains(mbr) ) return (Member)members.get(members.indexOf(mbr));
        else return super.getMember(mbr);
    }

    /**
     * Return the member that represents this node.
     *
     * @return Member
     */
    public Member getLocalMember(boolean incAlive) {
        if (this.localMember != null ) return localMember;
        else return super.getLocalMember(incAlive);
    }
    
    /**
     * Send notifications upwards
     * @param svc int
     * @throws ChannelException
     */
    public void start(int svc) throws ChannelException {
        if ( (Channel.SND_RX_SEQ&svc)==Channel.SND_RX_SEQ ) super.start(Channel.SND_RX_SEQ); 
        if ( (Channel.SND_TX_SEQ&svc)==Channel.SND_TX_SEQ ) super.start(Channel.SND_TX_SEQ); 
        final Member[] mbrs = (Member[])members.toArray(new Member[members.size()]);
        final ChannelInterceptorBase base = this;
        Thread t = new Thread() {
            public void run() {
                for (int i=0; i<mbrs.length; i++ ) {
                    base.memberAdded(mbrs[i]);
                }
            }
        };
        t.start();
        super.start(svc & (~Channel.SND_RX_SEQ) & (~Channel.SND_TX_SEQ));
    }

}