/*
 * Copyright (c) 2008-2009, Motorola, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Motorola, Inc. nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.obex;

/**
 * The <code>ServerRequestHandler</code> class defines an event listener that will respond to OBEX
 * requests made to the server.
 *
 * <p>The <code>onConnect()</code>, <code>onSetPath()</code>, <code>onDelete()</code>, <code>onGet()
 * </code>, and <code>onPut()</code> methods may return any response code defined in the <code>
 * ResponseCodes</code> class except for <code>OBEX_HTTP_CONTINUE</code>. If <code>
 * OBEX_HTTP_CONTINUE</code> or a value not defined in the <code>ResponseCodes</code> class is
 * returned, the server implementation will send an <code>OBEX_HTTP_INTERNAL_ERROR</code> response
 * to the client.
 *
 * <p><STRONG>Connection ID and Target Headers</STRONG>
 *
 * <p>According to the IrOBEX specification, a packet may not contain a Connection ID and Target
 * header. Since the Connection ID header is managed by the implementation, it will not send a
 * Connection ID header, if a Connection ID was specified, in a packet that has a Target header. In
 * other words, if an application adds a Target header to a <code>HeaderSet</code> object used in an
 * OBEX operation and a Connection ID was specified, no Connection ID will be sent in the packet
 * containing the Target header.
 *
 * <p><STRONG>CREATE-EMPTY Requests</STRONG>
 *
 * <p>A CREATE-EMPTY request allows clients to create empty objects on the server. When a
 * CREATE-EMPTY request is received, the <code>onPut()</code> method will be called by the
 * implementation. To differentiate between a normal PUT request and a CREATE-EMPTY request, an
 * application must open the <code>InputStream</code> from the <code>Operation</code> object passed
 * to the <code>onPut()</code> method. For a PUT request, the application will be able to read Body
 * data from this <code>InputStream</code>. For a CREATE-EMPTY request, there will be no Body data
 * to read. Therefore, a call to <code>InputStream.read()</code> will return -1.
 */
public class ServerRequestHandler {

    private long mConnectionId;

    /** Creates a <code>ServerRequestHandler</code>. */
    protected ServerRequestHandler() {
        /*
         * A connection ID of -1 implies there is no connection ID
         */
        mConnectionId = -1;
    }

    /**
     * Sets the connection ID header to include in the reply packets.
     *
     * @param connectionId the connection ID to use; -1 if no connection ID should be sent
     * @throws IllegalArgumentException if <code>id</code> is not in the range -1 to
     *     2<sup>32</sup>-1
     * @hide
     */
    public void setConnectionId(final long connectionId) {
        if ((connectionId < -1) || (connectionId > 0xFFFFFFFFL)) {
            throw new IllegalArgumentException("Illegal Connection ID");
        }
        mConnectionId = connectionId;
    }

    /**
     * Retrieves the connection ID that is being used in the present connection. This method will
     * return -1 if no connection ID is being used.
     *
     * @return the connection id being used or -1 if no connection ID is being used
     * @hide
     */
    public long getConnectionId() {
        return mConnectionId;
    }

    /**
     * Called when a CONNECT request is received.
     *
     * <p>If this method is not implemented by the class that extends this class, <code>onConnect()
     * </code> will always return an <code>OBEX_HTTP_OK</code> response code.
     *
     * <p>The headers received in the request can be retrieved from the <code>request</code>
     * argument. The headers that should be sent in the reply must be specified in the <code>reply
     * </code> argument.
     *
     * @param request contains the headers sent by the client; <code>request</code> will never be
     *     <code>null</code>
     * @param reply the headers that should be sent in the reply; <code>reply</code> will never be
     *     <code>null</code>
     * @return a response code defined in <code>ResponseCodes</code> that will be returned to the
     *     client; if an invalid response code is provided, the <code>OBEX_HTTP_INTERNAL_ERROR
     *     </code> response code will be used
     */
    public int onConnect(HeaderSet request, HeaderSet reply) {
        return ResponseCodes.OBEX_HTTP_OK;
    }

    /**
     * Called when a DISCONNECT request is received.
     *
     * <p>The headers received in the request can be retrieved from the <code>request</code>
     * argument. The headers that should be sent in the reply must be specified in the <code>reply
     * </code> argument.
     *
     * @param request contains the headers sent by the client; <code>request</code> will never be
     *     <code>null</code>
     * @param reply the headers that should be sent in the reply; <code>reply</code> will never be
     *     <code>null</code>
     */
    public void onDisconnect(HeaderSet request, HeaderSet reply) {}

    /**
     * Called when a SETPATH request is received.
     *
     * <p>If this method is not implemented by the class that extends this class, <code>onSetPath()
     * </code> will always return an <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
     *
     * <p>The headers received in the request can be retrieved from the <code>request</code>
     * argument. The headers that should be sent in the reply must be specified in the <code>reply
     * </code> argument.
     *
     * @param request contains the headers sent by the client; <code>request</code> will never be
     *     <code>null</code>
     * @param reply the headers that should be sent in the reply; <code>reply</code> will never be
     *     <code>null</code>
     * @param backup <code>true</code> if the client requests that the server back up one directory
     *     before changing to the path described by <code>name</code>; <code>false</code> to apply
     *     the request to the present path
     * @param create <code>true</code> if the path should be created if it does not already exist;
     *     <code>false</code> if the path should not be created if it does not exist and an error
     *     code should be returned
     * @return a response code defined in <code>ResponseCodes</code> that will be returned to the
     *     client; if an invalid response code is provided, the <code>OBEX_HTTP_INTERNAL_ERROR
     *     </code> response code will be used
     */
    public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) {

        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
    }

    /**
     * Called when a DELETE request is received.
     *
     * <p>If this method is not implemented by the class that extends this class, <code>onDelete()
     * </code> will always return an <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
     *
     * <p>The headers received in the request can be retrieved from the <code>request</code>
     * argument. The headers that should be sent in the reply must be specified in the <code>reply
     * </code> argument.
     *
     * @param request contains the headers sent by the client; <code>request</code> will never be
     *     <code>null</code>
     * @param reply the headers that should be sent in the reply; <code>reply</code> will never be
     *     <code>null</code>
     * @return a response code defined in <code>ResponseCodes</code> that will be returned to the
     *     client; if an invalid response code is provided, the <code>OBEX_HTTP_INTERNAL_ERROR
     *     </code> response code will be used
     */
    public int onDelete(HeaderSet request, HeaderSet reply) {
        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
    }

    /** Called when a ABORT request is received. */
    public int onAbort(HeaderSet request, HeaderSet reply) {
        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
    }

    /**
     * Called when a PUT request is received.
     *
     * <p>If this method is not implemented by the class that extends this class, <code>onPut()
     * </code> will always return an <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
     *
     * <p>If an ABORT request is received during the processing of a PUT request, <code>op</code>
     * will be closed by the implementation.
     *
     * @param operation contains the headers sent by the client and allows new headers to be sent in
     *     the reply; <code>op</code> will never be <code>null</code>
     * @return a response code defined in <code>ResponseCodes</code> that will be returned to the
     *     client; if an invalid response code is provided, the <code>OBEX_HTTP_INTERNAL_ERROR
     *     </code> response code will be used
     */
    public int onPut(Operation operation) {
        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
    }

    /**
     * Called when a GET request is received.
     *
     * <p>If this method is not implemented by the class that extends this class, <code>onGet()
     * </code> will always return an <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
     *
     * <p>If an ABORT request is received during the processing of a GET request, <code>op</code>
     * will be closed by the implementation.
     *
     * @param operation contains the headers sent by the client and allows new headers to be sent in
     *     the reply; <code>op</code> will never be <code>null</code>
     * @return a response code defined in <code>ResponseCodes</code> that will be returned to the
     *     client; if an invalid response code is provided, the <code>OBEX_HTTP_INTERNAL_ERROR
     *     </code> response code will be used
     */
    public int onGet(Operation operation) {
        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
    }

    /**
     * Called when this object attempts to authenticate a client and the authentication request
     * fails because the response digest in the authentication response header was wrong.
     *
     * <p>If this method is not implemented by the class that extends this class, this method will
     * do nothing.
     *
     * @param userName the user name returned in the authentication response; <code>null</code> if
     *     no user name was provided in the response
     */
    public void onAuthenticationFailure(byte[] userName) {}

    /**
     * Called by ServerSession to update the status of current transaction
     *
     * <p>If this method is not implemented by the class that extends this class, this method will
     * do nothing.
     */
    public void updateStatus(String message) {}

    /**
     * Called when session is closed.
     *
     * <p>If this method is not implemented by the class that extends this class, this method will
     * do nothing.
     */
    public void onClose() {}

    /**
     * Override to add Single Response Mode support - e.g. if the supplied transport is l2cap.
     *
     * @return True if SRM is supported, else False
     */
    public boolean isSrmSupported() {
        return false;
    }
}
