/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axis2.clustering.tribes;

import org.apache.axis2.clustering.ClusteringConstants;
import org.apache.axis2.clustering.control.wka.MemberJoinedCommand;
import org.apache.axis2.clustering.control.wka.MemberListCommand;
import org.apache.axis2.clustering.management.GroupManagementAgent;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.RemoteProcessException;
import org.apache.catalina.tribes.group.Response;
import org.apache.catalina.tribes.group.RpcChannel;
import org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor;
import org.apache.catalina.tribes.membership.MemberImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Responsible for managing the membership. Handles membership changes.
 */
public class MembershipManager {

    private static final Log log = LogFactory.getLog(MembershipManager.class);

    private RpcChannel rpcMembershipChannel;
    private StaticMembershipInterceptor staticMembershipInterceptor;

    /**
     * The domain corresponding to the membership handled by this MembershipManager
     */
    private byte[] domain;
    private GroupManagementAgent groupManagementAgent;
    private ConfigurationContext configContext;


    /**
     * List of current members in the cluster. Only the members who are alive will be in this
     * list
     */
    private final List<Member> members = new ArrayList<Member>();

    /**
     * List of Well-Known members. These members may or may not be alive at a given moment.
     */
    private final List<Member> wkaMembers = new ArrayList<Member>();

    /**
     * List of Well-Known members which have not responded to the MEMBER_LIST message.
     * We need to retry sending the MEMBER_LIST message to these members until they respond,
     * otherwise, we cannot be sure whether these WKA members added the members in the MEMBER_LIST
     */
    private final List<Member> nonRespondingWkaMembers = new CopyOnWriteArrayList<Member>();

    /**
     * The member representing this node
     */
    private Member localMember;

    /**
     *
     */
    private boolean isMemberListResponseReceived;

    public MembershipManager(ConfigurationContext configContext) {
        this.configContext = configContext;
    }

    public MembershipManager() {
    }

    public void setRpcMembershipChannel(RpcChannel rpcMembershipChannel) {
        this.rpcMembershipChannel = rpcMembershipChannel;
    }

    public RpcChannel getRpcMembershipChannel() {
        return rpcMembershipChannel;
    }

    public void setupStaticMembershipManagement(StaticMembershipInterceptor staticMembershipInterceptor) {
        this.staticMembershipInterceptor = staticMembershipInterceptor;
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleWithFixedDelay(new MemberListSenderTask(), 5, 5, TimeUnit.SECONDS);
    }

    public void setGroupManagementAgent(GroupManagementAgent groupManagementAgent) {
        this.groupManagementAgent = groupManagementAgent;
    }

    public void setDomain(byte[] domain) {
        this.domain = domain;
    }

    public byte[] getDomain() {
        return domain;
    }

    public Member getLocalMember() {
        return localMember;
    }

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

    public void addWellKnownMember(Member wkaMember) {
        wkaMembers.add(wkaMember);
    }

    public void removeWellKnownMember(Member wkaMember) {
        wkaMembers.remove(wkaMember);
    }

    /**
     * A new member is added
     *
     * @param member The new member that joined the cluster
     * @return true  If the member was added to the <code>members</code> array; false, otherwise.
     */
    public boolean memberAdded(Member member) {

        if (log.isDebugEnabled()) {
            log.debug("members.contains(member) =" + members.contains(member));
            log.debug("Is in my domain: " + TribesUtil.isInDomain(member, domain));
        }

        // If this member already exists or if the member belongs to another domain,
        // there is no need to add it
        if (members.contains(member) || !TribesUtil.isInDomain(member, domain)) {
            return false;
        }

        if (staticMembershipInterceptor != null) { // this interceptor is null when multicast based scheme is used
            staticMembershipInterceptor.addStaticMember(member);
            if (log.isDebugEnabled()) {
                log.debug("Added static member " + TribesUtil.getName(member));
            }
        }

        boolean shouldAddMember = localMember == null ||
                                  TribesUtil.areInSameDomain(localMember, member);

        // If this member is a load balancer, notify the respective load balance event handler?
        if (groupManagementAgent != null) {
            log.info("Application member " + TribesUtil.getName(member) + " joined group " +
                     new String(member.getDomain()));
            groupManagementAgent.applicationMemberAdded(TribesUtil.toAxis2Member(member));
        }

        if (shouldAddMember) {
            boolean wkaMemberBelongsToLocalDomain = true;
            if (rpcMembershipChannel != null && isLocalMemberInitialized() &&
                wkaMembers.contains(member)) { // if it is a well-known member

                log.info("A WKA member " + TribesUtil.getName(member) +
                         " just joined the group. Sending MEMBER_LIST message.");
                wkaMemberBelongsToLocalDomain = sendMemberListToWellKnownMember(member);
            }
            if (wkaMemberBelongsToLocalDomain) {
                members.add(member);
                if (log.isDebugEnabled()) {
                    log.debug("Added group member " + TribesUtil.getName(member) + " to domain " +
                              new String(member.getDomain()));
                }
                return true;
            }
        }
        return false;
    }

    /**
     * Task which send MEMBER_LIST messages to WKA members which have not yet responded to the
     * MEMBER_LIST message
     */
    private class MemberListSenderTask implements Runnable {
        public void run() {
            try {
                if (nonRespondingWkaMembers != null && !nonRespondingWkaMembers.isEmpty()) {
                    for (Member wkaMember : nonRespondingWkaMembers) {
                        if (wkaMember != null) {
                            sendMemberListToWellKnownMember(wkaMember);
                        }
                    }
                }
            } catch (Throwable e) {
                log.error("Could not send MemberList to WKA Members", e);
            }
        }
    }

    /**
     * Send MEMBER_LIST message to WKA member
     *
     * @param wkaMember The WKA member to whom the MEMBER_LIST has to be sent
     * @return true - if the WKA member belongs to the domain of this local member
     */
    private boolean sendMemberListToWellKnownMember(Member wkaMember) {
        /*if (wkaMember.isFailing() || wkaMember.isSuspect()) {
            return false;
        }*/
        // send the member list to it
        MemberListCommand memListCmd;
        try {
            memListCmd = new MemberListCommand();
            List<Member> members = new ArrayList<Member>(this.members);
            members.add(localMember); // Need to set the local member too
            memListCmd.setMembers(members.toArray(new Member[members.size()]));

            Response[] responses =
                    rpcMembershipChannel.send(new Member[]{wkaMember}, memListCmd,
                                              RpcChannel.ALL_REPLY,
                                              Channel.SEND_OPTIONS_ASYNCHRONOUS |
                                              TribesConstants.MEMBERSHIP_MSG_OPTION, 10000);

            // Once a response is received from the WKA member to the MEMBER_LIST message,
            // if it does not belong to this domain, simply remove it from the members
            if (responses != null && responses.length > 0 && responses[0] != null) {
                nonRespondingWkaMembers.remove(wkaMember);
                Member source = responses[0].getSource();
                if (!TribesUtil.areInSameDomain(source, wkaMember)) {
                    if (log.isDebugEnabled()) {
                        log.debug("WKA Member " + TribesUtil.getName(source) +
                                  " does not belong to local domain " + new String(domain) +
                                  ". Hence removing it from the list.");
                    }
                    return false;
                }
            } else { // No response from WKA member
                nonRespondingWkaMembers.add(wkaMember);
            }
        } catch (Exception e) {
            String errMsg = "Could not send MEMBER_LIST to well-known member " +
                            TribesUtil.getName(wkaMember);
            log.error(errMsg, e);
            throw new RemoteProcessException(errMsg, e);
        }
        return true;
    }

    /**
     * Send the list of members to the <code>member</code>
     *
     * @param member The member to whom the member list has to be sent
     */
    public void sendMemberList(Member member) {
        try {
            MemberListCommand memListCmd = new MemberListCommand();
            List<Member> members = new ArrayList<Member>(this.members);
            memListCmd.setMembers(members.toArray(new Member[members.size()]));
            rpcMembershipChannel.send(new Member[]{member}, memListCmd, RpcChannel.ALL_REPLY,
                                      Channel.SEND_OPTIONS_ASYNCHRONOUS |
                                      TribesConstants.MEMBERSHIP_MSG_OPTION, 10000);
            if (log.isDebugEnabled()) {
                log.debug("Sent MEMBER_LIST to " + TribesUtil.getName(member));
            }
        } catch (Exception e) {
            String errMsg = "Could not send MEMBER_LIST to member " + TribesUtil.getName(member);
            log.error(errMsg, e);
            throw new RemoteProcessException(errMsg, e);
        }
    }

    /**
     * Inform all members that a particular member just joined
     *
     * @param member The member who just joined
     */
    public void sendMemberJoinedToAll(Member member) {
        try {

            MemberJoinedCommand cmd = new MemberJoinedCommand();
            cmd.setMember(member);
            ArrayList<Member> membersToSend = (ArrayList<Member>) (((ArrayList) members).clone());
            membersToSend.remove(member); // Do not send MEMBER_JOINED to the new member who just joined

            if (membersToSend.size() > 0) {
                rpcMembershipChannel.send(membersToSend.toArray(new Member[membersToSend.size()]), cmd,
                                          RpcChannel.ALL_REPLY,
                                          Channel.SEND_OPTIONS_ASYNCHRONOUS |
                                          TribesConstants.MEMBERSHIP_MSG_OPTION,
                                          10000);
                if (log.isDebugEnabled()) {
                    log.debug("Sent MEMBER_JOINED[" + TribesUtil.getName(member) +
                              "] to all members in domain " + new String(domain));
                }
            }
        } catch (Exception e) {
            String errMsg = "Could not send MEMBER_JOINED[" + TribesUtil.getName(member) +
                            "] to all members ";
            log.error(errMsg, e);
            throw new RemoteProcessException(errMsg, e);
        }
    }

    private boolean isLocalMemberInitialized() {
        if (configContext == null) {
            return false;
        }
        Object clusterInitialized =
                configContext.getPropertyNonReplicable(ClusteringConstants.CLUSTER_INITIALIZED);
        return clusterInitialized != null && clusterInitialized.equals("true");
    }

    /**
     * A member disappeared
     *
     * @param member The member that left the cluster
     */
    public void memberDisappeared(Member member) {
        members.remove(member);
        nonRespondingWkaMembers.remove(member);

        // Is this an application domain member?
        if (groupManagementAgent != null) {
            groupManagementAgent.applicationMemberRemoved(TribesUtil.toAxis2Member(member));
        }
    }

    /**
     * Get the list of current members
     *
     * @return list of current members
     */
    public Member[] getMembers() {
        return members.toArray(new Member[members.size()]);
    }

    /**
     * Get the member that has been alive for the longest time
     *
     * @return The member that has been alive for the longest time
     */
    public Member getLongestLivingMember() {
        Member longestLivingMember = null;
        if (members.size() > 0) {
            Member member0 = members.get(0);
            long longestAliveTime = member0.getMemberAliveTime();
            longestLivingMember = member0;
            for (Member member : members) {
                if (longestAliveTime < member.getMemberAliveTime()) {
                    longestAliveTime = member.getMemberAliveTime();
                    longestLivingMember = member;
                }
            }
        }
        return longestLivingMember;
    }

    /**
     * Get a random member from the list of current members
     *
     * @return A random member from the list of current members
     */
    public Member getRandomMember() {
        if (members.size() == 0) {
            return null;
        }
        int memberIndex = new Random().nextInt(members.size());
        return members.get(memberIndex);
    }

    /**
     * Check whether there are any members
     *
     * @return true if there are other members, false otherwise
     */
    public boolean hasMembers() {
        return members.size() > 0;
    }

    /**
     * Get a member
     *
     * @param member The member to be found
     * @return The member, if it is found
     */
    public Member getMember(Member member) {
        if (hasMembers()) {
            MemberImpl result = null;
            for (int i = 0; i < this.members.size() && result == null; i++) {
                if (members.get(i).equals(member)) {
                    result = (MemberImpl) members.get(i);
                }
            }
            return result;
        }
        return null;
    }
}
