/*
 * Copyright (C) 2005 Alfresco, Inc.
 *
 * Licensed under the Mozilla Public License version 1.1 
 * with a permitted attribution clause. You may obtain a
 * copy of the License at
 *
 *   http://www.alfresco.org/legal/license.txt
 *
 * 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.alfresco.filesys.smb.server.notify;

import java.util.Vector;

import org.alfresco.filesys.server.filesys.NetworkFile;
import org.alfresco.filesys.smb.server.SMBSrvSession;

/**
 * Notify Change Request List Class
 */
public class NotifyRequestList
{

    // List of notify change requests

    private Vector<NotifyRequest> m_requests;

    /**
     * Default constructor
     */
    public NotifyRequestList()
    {
        m_requests = new Vector<NotifyRequest>();
    }

    /**
     * Return the specified request
     * 
     * @param idx int
     * @return NotifyRequest
     */
    public final synchronized NotifyRequest getRequest(int idx)
    {

        // Range check the index

        if (idx >= m_requests.size())
            return null;

        // Return the notify request

        return (NotifyRequest) m_requests.elementAt(idx);
    }

    /**
     * Return the global filter mask, generated by combining all of the pending notify request
     * filters
     * 
     * @return int
     */
    public final synchronized int getGlobalFilter()
    {

        // Loop through all the requests

        int filter = 0;

        if (m_requests.size() > 0)
        {

            // Build the global filter mask from all pending requests

            for (int i = 0; i < m_requests.size(); i++)
            {
                NotifyRequest req = m_requests.get(i);
                filter |= req.getFilter();
            }
        }

        // Return the filter mask

        return filter;
    }

    /**
     * Add a request to the list
     * 
     * @param req NotifyRequest
     */
    public final synchronized void addRequest(NotifyRequest req)
    {
        m_requests.addElement(req);
    }

    /**
     * Find the notify request for the matching ids
     * 
     * @param mid int
     * @param tid int
     * @param uid int
     * @param pid int
     * @return NotifyRequest
     */
    public final synchronized NotifyRequest findRequest(int mid, int tid, int uid, int pid)
    {

        // Search for the required request, and remove it from the list

        for (int i = 0; i < m_requests.size(); i++)
        {

            // Get the current request

            NotifyRequest curReq = (NotifyRequest) m_requests.elementAt(i);
            if (curReq.getMultiplexId() == mid && curReq.getTreeId() == tid && curReq.getUserId() == uid
                    && curReq.getProcessId() == pid)
            {

                // Return the request

                return curReq;
            }
        }

        // Request not found in the list

        return null;
    }

    /**
     * Find the notify request for the specified directory and filter
     * 
     * @param dir NetworkFile
     * @param filter int
     * @param watchTree boolean
     */
    public final synchronized NotifyRequest findRequest(NetworkFile dir, int filter, boolean watchTree)
    {

        // Search for the required request

        for (int i = 0; i < m_requests.size(); i++)
        {

            // Get the current request

            NotifyRequest curReq = (NotifyRequest) m_requests.elementAt(i);
            if (curReq.getDirectory() == dir && curReq.getFilter() == filter && curReq.hasWatchTree() == watchTree)
            {

                // Return the request

                return curReq;
            }
        }

        // Request not found in the list

        return null;
    }

    /**
     * Remove a request from the list
     * 
     * @param req NotifyRequest
     */
    public final synchronized NotifyRequest removeRequest(NotifyRequest req)
    {

        // Search for the required request, and remove it from the list

        for (int i = 0; i < m_requests.size(); i++)
        {

            // Get the current request

            NotifyRequest curReq = (NotifyRequest) m_requests.elementAt(i);
            if (curReq == req)
            {

                // Remove the request from the list

                m_requests.removeElementAt(i);
                return curReq;
            }
        }

        // Request not found in the list

        return null;
    }

    /**
     * Remove a request from the list
     * 
     * @param idx int
     */
    public final synchronized NotifyRequest removeRequestAt(int idx)
    {

        // Check if the request index is valid

        if (idx < 0 || idx >= m_requests.size())
            return null;

        // Remove the specified request

        NotifyRequest req = (NotifyRequest) m_requests.elementAt(idx);
        m_requests.removeElementAt(idx);
        return req;
    }

    /**
     * Remove all requests for the specified session
     * 
     * @param sess SMBSrvSession
     */
    public final synchronized void removeAllRequestsForSession(SMBSrvSession sess)
    {

        // Search for the required requests, and remove from the list

        int idx = 0;

        while (idx < m_requests.size())
        {

            // Get the current request

            NotifyRequest curReq = (NotifyRequest) m_requests.elementAt(idx);
            if (curReq.getSession() == sess)
            {

                // Remove the request from the list

                m_requests.removeElementAt(idx);
            }
            else
                idx++;
        }
    }

    /**
     * Remove all requests for the specified session and tree connection
     * 
     * @param sess SMBSrvSession
     * @param tid int
     */
    public final synchronized void removeAllRequestsForSession(SMBSrvSession sess, int tid)
    {

        // Search for the required requests, and remove from the list

        int idx = 0;

        while (idx < m_requests.size())
        {

            // Get the current request

            NotifyRequest curReq = (NotifyRequest) m_requests.elementAt(idx);
            if (curReq.getSession() == sess && curReq.getTreeId() == tid)
            {

                // Remove the request from the list

                m_requests.removeElementAt(idx);
            }
            else
                idx++;
        }
    }

    /**
     * Remove all requests from the list
     */
    public final synchronized void clearRequestList()
    {
        m_requests.removeAllElements();
    }

    /**
     * Return the request list size
     * 
     * @return int
     */
    public final synchronized int numberOfRequests()
    {
        return m_requests.size();
    }
}
