/*
 * 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.
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 */
package org.jvnet.glassfish.comms.replication.sessmgmt;

import com.ericsson.ssa.sip.SipApplicationSessionImpl;
import com.ericsson.ssa.sip.SipSessionBase;
import com.ericsson.ssa.sip.SipSessionDialogImpl;
import com.ericsson.ssa.sip.SipSessionManagerBase;
import com.sun.enterprise.ee.web.sessmgmt.ReplicationState;

import com.sun.enterprise.ee.web.sessmgmt.ReplicationUtil;

import java.io.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;

import org.jvnet.glassfish.comms.util.LogUtil;

public class HASipApplicationSession extends SipApplicationSessionImpl {

    private static final Logger _logger = Logger.getLogger(LogUtil.SIP_LOG_DOMAIN);
    // XXX make this a configurable item?
    private static final long DELTA = 10 * 1000; // 10 secs
   
    private transient boolean isDirty = false;
    private transient AtomicLong version;
    private transient SipApplicationSessionExtraParams extraParams;
    private transient String previousOwnerInstanceName;
    private transient String currentOwnerInstanceName;
    private transient boolean wasLockedOnRemoteInstance = false;
    protected transient boolean isReplicated = false;

    /**
     * Constructor.
     */
    public HASipApplicationSession(SipSessionManagerBase manager, String id) {
        super(manager, id);
        version = new AtomicLong(-1);
        extraParams = new SipApplicationSessionExtraParams(this);
        currentOwnerInstanceName = ReplicationUtil.getInstanceName();
    }

    /**
     * Gets the name of the instance.that previously owned this
     * SipApplicationSession.
     *
     * @return The name of the instance that previously owned this
     *         SipApplicationSession
     */
    public String getPreviousOwnerInstanceName() {
        return previousOwnerInstanceName;
    }

    /**
     * Gets the name of the instance.that currently owns this
     * SipApplicationSession.
     *
     * @return The name of the instance that currently owns this
     *         SipApplicationSession
     */
    public String getCurrentOwnerInstanceName() {
        return currentOwnerInstanceName;
    }

    /**
     * Checks whether this session is dirty or not.
     *
     * @return true if this session has been marked as dirty, false otherwise
     */
    public boolean isDirty() {
        return isDirty;
    }

    /**
     * Marks this session as dirty or non-dirty.
     *
     * @param isDirty The dirty flag
     */
    public void setDirty(boolean isDirty) {
        this.isDirty = isDirty;
    }

    /**
     * Increments the version of this SipApplicationSession.
     */
    public void incrementVersion() {
        version.incrementAndGet();
    }

    /**
     * Gets the version of this SipApplicationSession.
     *
     * @return The version of this SipApplicationSession
     */
    public long getVersion() {
        return version.get();
    }

    /**
     * Sets the version of this SipApplicationSession.
     *
     * @value The new version of this SipApplicationSession
     */
    public void setVersion(long value) {
        version.getAndSet(value);
    }
    
    /** 
     * is the SipApplicationSession persistent
     */    
    public boolean isReplicated() {
        return isReplicated;
    }
    
    /** 
     * this sets the persistent flag
     */    
    public void setReplicated(boolean value) {
        isReplicated = value;
    }    

    public SipApplicationSessionExtraParams getExtraParameters() {
        return extraParams;
    }
    
    /**
     * Updates this SipApplicationSession with the given extra 
     * parameters.
     *
     * @param extraParams The serialized SipApplicationSessionExtraParams 
     * used to update this
     * SipApplicationSession
     */
    public void update(byte[] extraParamsState) {        
        
        SipApplicationSessionExtraParams extraParams = null;
        if(extraParamsState != null) {
            try {
                extraParams 
                    = (SipApplicationSessionExtraParams)ReplicationState.getObjectValue(extraParamsState);
                this.updatePFieldExpirationTimeOnSASOnly(extraParams.getExpirationTime());
            } catch (Exception ex) {
                _logger.warning("unable to deserialize SipApplicationSession extraParams for id " + this.getId() + ":" + ex);
            }
        } 
    }        

    /**
     * Activates the object graph belonging to this SAS.
     */
    void activateGraph() {
        // FIXME
    }

    /**
     * Validates this SipApplicationSession.
     *
     * This is called during activation.
     */
    protected boolean validate() {
        if (wasLockedOnRemoteInstance()) {
            // Foreground locked on remote instance
            return false;
        }
        return super.validate();
    }

    boolean wasLockedOnRemoteInstance() {
        return wasLockedOnRemoteInstance;
    }

    private void writeObject(ObjectOutputStream oos)
            throws IOException {
        oos.writeObject(version);
        oos.writeObject(currentOwnerInstanceName);
        oos.writeBoolean(isForegroundLocked());
    }

    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        version = (AtomicLong) in.readObject();
        previousOwnerInstanceName = (String) in.readObject();
        wasLockedOnRemoteInstance = in.readBoolean();
        currentOwnerInstanceName = ReplicationUtil.getInstanceName();
        extraParams = new SipApplicationSessionExtraParams(this);
    }

    public String toString() {
        return description + ":version:" + getVersion(); 
    }
    
    @Override
    protected void setPFieldExpirationTime(long anExpirationTime) {
        // when called as part of the business logic; the value to be saved
        // and the children updated
        updatePFieldExpirationTimeOnSASOnly(anExpirationTime);
        // load all the children and set their expiration time
        for (SipSessionBase ss : getPFieldSipSessions()) {
            if (anExpirationTime > 0) {
                ((HASipSession) ss).setExpirationTime(anExpirationTime+DELTA);
            } else {
                ((HASipSession) ss).setExpirationTime(-1L);
            }

        }
    }
    
    private void updatePFieldExpirationTimeOnSASOnly(long anExpirationTime) {
        // when called as part of the restore logic only update the local value
        super.setPFieldExpirationTime(anExpirationTime);
    }
    
}
