/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the license at
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
 */
package com.ericsson.ssa.sip;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipSessionsUtil;
import com.ericsson.ssa.config.ConvergedContext;
import com.ericsson.ssa.config.ConvergedContextImpl;
import com.ericsson.ssa.sip.wrapper.WrapperFactorySet;

/**
 * Implementation class of SipSessionsUtil interface.
 *
 * @author jluehe
 */
public class SipSessionsUtilImpl implements SipSessionsUtil {
    private ConvergedContextImpl ctx;
    private ConcurrentHashMap<Object, String> linkedSessions =
        new ConcurrentHashMap<Object, String>();

    // Does this SipSessionsUtil have cross-SAR visibility, i.e., does
    // it have access to the SipSessionManagers associated with sibling SAR
    // files embedded in the same EAR file, or does it have access to only
    // its own SipSessionManager?
    private boolean hasCrossSarVisibility = false;

    /**
     * Constructor.
     */
    public SipSessionsUtilImpl(ConvergedContextImpl ctx) {
        this(ctx, false);
    }

    /**
     * Constructor.
     */
    public SipSessionsUtilImpl(ConvergedContextImpl ctx,
                               boolean hasCrossSarVisibility) {
        this.ctx = ctx;
        this.hasCrossSarVisibility = hasCrossSarVisibility;
    }

    /**
     * Gets the SipApplicationSession with the given id.
     *
     * @param sasId The id of the requested SipApplicationSession
     *
     * @return The SipApplicationSession with the given id, or null if no
     * such SipApplicationSession exists
     */
    public SipApplicationSession getApplicationSession(String sasId) {
        if (sasId == null || !SipApplicationSessionUtil.isLocal(sasId)) {
            return null;
        }

        SipApplicationSessionBase sas = null;
        if (hasCrossSarVisibility) {
            Set siblings = ctx.getSiblingContexts();
            if (siblings != null) {
                Iterator iter = siblings.iterator();
                while (sas == null && iter.hasNext()) {
                    ConvergedContext cc = (ConvergedContext) iter.next();
                    SipSessionManager manager = cc.getSipSessionManager();
                    if (manager != null) {
                        sas = manager.findSipApplicationSession(sasId);
                    }
                }
            }
        } else {
            SipSessionManager manager = ctx.getSipSessionManager();
            if (manager != null) {
                sas = manager.findSipApplicationSession(sasId);
            }
        }

        if (sas != null && sas.isReplicable()) {
            return WrapperFactorySet.getSASFactory().wrap(sas, null);
        }

        return sas;
    }

    public void linkSession(Object key, String applicationSessionId) {
        linkedSessions.put(key, applicationSessionId);
    }

    public SipApplicationSession getLinkedSession(Object key) {
        return getApplicationSession(linkedSessions.get(key));
    }

    public void removeSessionsMapping(SipApplicationSessionImpl sas) {
        // TODO make a more preforment delete from linked sessions and not
        // a scan.
        Iterator<String> i = linkedSessions.values().iterator();

        while (i.hasNext()) {
            if (sas.getId().equals(i.next())) {
                i.remove();

                break;
            }
        }
    }
}
