/*
 * 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.catalina.ha.session;

/**
 * This class is used to track the series of actions that happens when
 * a request is executed. These actions will then translate into invocations of methods
 * on the actual session.
 * This class is NOT thread safe. One DeltaRequest per session
 * @version 1.0
 */

import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.Principal;
import java.util.LinkedList;

import org.apache.catalina.SessionListener;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.tomcat.util.res.StringManager;


public class DeltaRequest implements Externalizable {

    public static final org.apache.juli.logging.Log log =
        org.apache.juli.logging.LogFactory.getLog( DeltaRequest.class );

    /**
     * The string manager for this package.
     */
    protected static final StringManager sm = StringManager
            .getManager(Constants.Package);

    public static final int TYPE_ATTRIBUTE = 0;
    public static final int TYPE_PRINCIPAL = 1;
    public static final int TYPE_ISNEW = 2;
    public static final int TYPE_MAXINTERVAL = 3;
    public static final int TYPE_AUTHTYPE = 4;
    public static final int TYPE_LISTENER = 5;

    public static final int ACTION_SET = 0;
    public static final int ACTION_REMOVE = 1;

    public static final String NAME_PRINCIPAL = "__SET__PRINCIPAL__";
    public static final String NAME_MAXINTERVAL = "__SET__MAXINTERVAL__";
    public static final String NAME_ISNEW = "__SET__ISNEW__";
    public static final String NAME_AUTHTYPE = "__SET__AUTHTYPE__";
    public static final String NAME_LISTENER = "__SET__LISTENER__";

    private String sessionId;
    private LinkedList<AttributeInfo> actions = new LinkedList<>();
    private final LinkedList<AttributeInfo> actionPool = new LinkedList<>();

    private boolean recordAllActions = false;

    public DeltaRequest() {

    }

    public DeltaRequest(String sessionId, boolean recordAllActions) {
        this.recordAllActions=recordAllActions;
        if(sessionId != null)
            setSessionId(sessionId);
    }


    public void setAttribute(String name, Object value) {
        int action = (value==null)?ACTION_REMOVE:ACTION_SET;
        addAction(TYPE_ATTRIBUTE,action,name,value);
    }

    public void removeAttribute(String name) {
        int action = ACTION_REMOVE;
        addAction(TYPE_ATTRIBUTE,action,name,null);
    }

    public void setMaxInactiveInterval(int interval) {
        int action = ACTION_SET;
        addAction(TYPE_MAXINTERVAL,action,NAME_MAXINTERVAL,Integer.valueOf(interval));
    }

    /**
     * Only support principals from type {@link GenericPrincipal GenericPrincipal}
     * @param p Session principal
     * @see GenericPrincipal
     */
    public void setPrincipal(Principal p) {
        int action = (p==null)?ACTION_REMOVE:ACTION_SET;
        GenericPrincipal gp = null;
        if (p != null) {
            if (p instanceof GenericPrincipal) {
                gp = (GenericPrincipal) p;
                if(log.isDebugEnabled())
                    log.debug(sm.getString("deltaRequest.showPrincipal", p.getName() , getSessionId()));
            } else
                log.error(sm.getString("deltaRequest.wrongPrincipalClass",p.getClass().getName()));
        }
        addAction(TYPE_PRINCIPAL, action, NAME_PRINCIPAL, gp);
    }

    public void setNew(boolean n) {
        int action = ACTION_SET;
        addAction(TYPE_ISNEW,action,NAME_ISNEW,Boolean.valueOf(n));
    }

    public void setAuthType(String authType) {
        int action = (authType==null)?ACTION_REMOVE:ACTION_SET;
        addAction(TYPE_AUTHTYPE,action,NAME_AUTHTYPE, authType);
    }

    public void addSessionListener(SessionListener listener) {
        addAction(TYPE_LISTENER, ACTION_SET, NAME_LISTENER ,listener);
    }

    public void removeSessionListener(SessionListener listener) {
        addAction(TYPE_LISTENER, ACTION_REMOVE, NAME_LISTENER ,listener);
    }

    protected void addAction(int type,
                             int action,
                             String name,
                             Object value) {
        AttributeInfo info = null;
        if ( this.actionPool.size() > 0 ) {
            try {
                info = actionPool.removeFirst();
            }catch ( Exception x ) {
                log.error(sm.getString("deltaRequest.removeUnable"),x);
                info = new AttributeInfo(type, action, name, value);
            }
            info.init(type,action,name,value);
        } else {
            info = new AttributeInfo(type, action, name, value);
        }
        //if we have already done something to this attribute, make sure
        //we don't send multiple actions across the wire
        if ( !recordAllActions) {
            try {
                actions.remove(info);
            } catch (java.util.NoSuchElementException x) {
                //do nothing, we wanted to remove it anyway
            }
        }
        //add the action
        actions.addLast(info);
    }

    public void execute(DeltaSession session, boolean notifyListeners) {
        if ( !this.sessionId.equals( session.getId() ) )
            throw new java.lang.IllegalArgumentException(sm.getString("deltaRequest.ssid.mismatch"));
        session.access();
        for ( int i=0; i<actions.size(); i++ ) {
            AttributeInfo info = actions.get(i);
            switch ( info.getType() ) {
                case TYPE_ATTRIBUTE:
                    if ( info.getAction() == ACTION_SET ) {
                        if ( log.isTraceEnabled() ) log.trace("Session.setAttribute('"+info.getName()+"', '"+info.getValue()+"')");
                        session.setAttribute(info.getName(), info.getValue(),notifyListeners,false);
                    }  else {
                        if ( log.isTraceEnabled() ) log.trace("Session.removeAttribute('"+info.getName()+"')");
                        session.removeAttribute(info.getName(),notifyListeners,false);
                    }

                    break;
                case TYPE_ISNEW:
                    if ( log.isTraceEnabled() ) log.trace("Session.setNew('"+info.getValue()+"')");
                    session.setNew(((Boolean)info.getValue()).booleanValue(),false);
                    break;
                case TYPE_MAXINTERVAL:
                    if ( log.isTraceEnabled() ) log.trace("Session.setMaxInactiveInterval('"+info.getValue()+"')");
                    session.setMaxInactiveInterval(((Integer)info.getValue()).intValue(),false);
                    break;
                case TYPE_PRINCIPAL:
                    Principal p = null;
                    if (info.getAction() == ACTION_SET) {
                        p = (Principal) info.getValue();
                    }
                    session.setPrincipal(p,false);
                    break;
                case TYPE_AUTHTYPE:
                    String authType = null;
                    if ( info.getAction() == ACTION_SET ) {
                        authType = (String)info.getValue();
                    }
                    session.setAuthType(authType,false);
                    break;
                case TYPE_LISTENER:
                    SessionListener listener = (SessionListener) info.getValue();
                    if (info.getAction() == ACTION_SET) {
                        session.addSessionListener(listener,false);
                    } else {
                        session.removeSessionListener(listener,false);
                    }
                    break;
                default :
                    throw new java.lang.IllegalArgumentException(sm.getString("deltaRequest.invalidAttributeInfoType", info));
            }//switch
        }//for
        session.endAccess();
        reset();
    }

    public void reset() {
        while ( actions.size() > 0 ) {
            try {
                AttributeInfo info = actions.removeFirst();
                info.recycle();
                actionPool.addLast(info);
            }catch  ( Exception x ) {
                log.error(sm.getString("deltaRequest.removeUnable"),x);
            }
        }
        actions.clear();
    }

    public String getSessionId() {
        return sessionId;
    }
    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
        if ( sessionId == null ) {
            new Exception(sm.getString("deltaRequest.ssid.null")).fillInStackTrace().printStackTrace();
        }
    }
    public int getSize() {
        return actions.size();
    }

    public void clear() {
        actions.clear();
        actionPool.clear();
    }

    @Override
    public void readExternal(java.io.ObjectInput in) throws IOException,ClassNotFoundException {
        //sessionId - String
        //recordAll - boolean
        //size - int
        //AttributeInfo - in an array
        reset();
        sessionId = in.readUTF();
        recordAllActions = in.readBoolean();
        int cnt = in.readInt();
        if (actions == null)
            actions = new LinkedList<>();
        else
            actions.clear();
        for (int i = 0; i < cnt; i++) {
            AttributeInfo info = null;
            if (this.actionPool.size() > 0) {
                try {
                    info = actionPool.removeFirst();
                } catch ( Exception x )  {
                    log.error(sm.getString("deltaRequest.removeUnable"),x);
                    info = new AttributeInfo();
                }
            }
            else {
                info = new AttributeInfo();
            }
            info.readExternal(in);
            actions.addLast(info);
        }//for
    }


    @Override
    public void writeExternal(java.io.ObjectOutput out ) throws java.io.IOException {
        //sessionId - String
        //recordAll - boolean
        //size - int
        //AttributeInfo - in an array
        out.writeUTF(getSessionId());
        out.writeBoolean(recordAllActions);
        out.writeInt(getSize());
        for ( int i=0; i<getSize(); i++ ) {
            AttributeInfo info = actions.get(i);
            info.writeExternal(out);
        }
    }

    /**
     * serialize DeltaRequest
     * @see DeltaRequest#writeExternal(java.io.ObjectOutput)
     *
     * @return serialized delta request
     * @throws IOException
     */
    protected byte[] serialize() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        writeExternal(oos);
        oos.flush();
        oos.close();
        return bos.toByteArray();
    }

    private static class AttributeInfo implements java.io.Externalizable {
        private String name = null;
        private Object value = null;
        private int action;
        private int type;

        public AttributeInfo() {
            this(-1, -1, null, null);
        }

        public AttributeInfo(int type,
                             int action,
                             String name,
                             Object value) {
            super();
            init(type,action,name,value);
        }

        public void init(int type,
                         int action,
                         String name,
                         Object value) {
            this.name = name;
            this.value = value;
            this.action = action;
            this.type = type;
        }

        public int getType() {
            return type;
        }

        public int getAction() {
            return action;
        }

        public Object getValue() {
            return value;
        }
        @Override
        public int hashCode() {
            return name.hashCode();
        }

        public String getName() {
            return name;
        }

        public void recycle() {
            name = null;
            value = null;
            type=-1;
            action=-1;
        }

        @Override
        public boolean equals(Object o) {
            if ( ! (o instanceof AttributeInfo ) ) return false;
            AttributeInfo other =  (AttributeInfo)o;
            return other.getName().equals(this.getName());
        }

        @Override
        public void readExternal(java.io.ObjectInput in ) throws IOException,ClassNotFoundException {
            //type - int
            //action - int
            //name - String
            //hasvalue - boolean
            //value - object
            type = in.readInt();
            action = in.readInt();
            name = in.readUTF();
            boolean hasValue = in.readBoolean();
            if ( hasValue ) value = in.readObject();
        }

        @Override
        public void writeExternal(java.io.ObjectOutput out) throws IOException {
            //type - int
            //action - int
            //name - String
            //hasvalue - boolean
            //value - object
            out.writeInt(getType());
            out.writeInt(getAction());
            out.writeUTF(getName());
            out.writeBoolean(getValue()!=null);
            if (getValue()!=null) out.writeObject(getValue());
        }

        @Override
        public String toString() {
            StringBuilder buf = new StringBuilder("AttributeInfo[type=");
            buf.append(getType()).append(", action=").append(getAction());
            buf.append(", name=").append(getName()).append(", value=").append(getValue());
            buf.append(", addr=").append(super.toString()).append("]");
            return buf.toString();
        }

    }

}
