/*
 * 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.tomcat.websocket;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;

import javax.websocket.CloseReason;
import javax.websocket.CloseReason.CloseCodes;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;

public class WsFrameClient extends WsFrameBase {

    private final Log log = LogFactory.getLog(WsFrameClient.class);
    private static final StringManager sm =
            StringManager.getManager(Constants.PACKAGE_NAME);

    private final AsyncChannelWrapper channel;
    private final CompletionHandler<Integer,Void> handler;
    // Not final as it may need to be re-sized
    private volatile ByteBuffer response;

    public WsFrameClient(ByteBuffer response, AsyncChannelWrapper channel,
            WsSession wsSession, Transformation transformation) {
        super(wsSession, transformation);
        this.response = response;
        this.channel = channel;
        this.handler = new WsFrameClientCompletionHandler();
    }


    void startInputProcessing() {
        try {
            processSocketRead();
        } catch (IOException e) {
            close(e);
        }
    }


    private void processSocketRead() throws IOException {

        while (response.hasRemaining()) {
            int remaining = response.remaining();

            int toCopy = Math.min(remaining, inputBuffer.length - writePos);

            // Copy remaining bytes read in HTTP phase to input buffer used by
            // frame processing
            response.get(inputBuffer, writePos, toCopy);
            writePos += toCopy;

            // Process the data we have
            processInputBuffer();
        }
        response.clear();

        // Get some more data
        if (isOpen()) {
            channel.read(response, null, handler);
        }
    }


    private final void close(Throwable t) {
        CloseReason cr;
        if (t instanceof WsIOException) {
            cr = ((WsIOException) t).getCloseReason();
        } else {
            cr = new CloseReason(
                CloseCodes.CLOSED_ABNORMALLY, t.getMessage());
        }

        try {
            wsSession.close(cr);
        } catch (IOException ignore) {
            // Ignore
        }
    }


    @Override
    protected boolean isMasked() {
        // Data is from the server so it is not masked
        return false;
    }


    @Override
    protected Log getLog() {
        return log;
    }


    private class WsFrameClientCompletionHandler
            implements CompletionHandler<Integer,Void> {

        @Override
        public void completed(Integer result, Void attachment) {
            if (result.intValue() == -1) {
                // BZ 57762. A dropped connection will get reported as EOF
                // rather than as an error so handle it here.
                if (isOpen()) {
                    // No close frame was received
                    close(new EOFException());
                }
                // No data to process
                return;
            }
            response.flip();
            try {
                processSocketRead();
            } catch (IOException e) {
                // Only send a close message on an IOException if the client
                // has not yet received a close control message from the server
                // as the IOException may be in response to the client
                // continuing to send a message after the server sent a close
                // control message.
                if (isOpen()) {
                    log.debug(sm.getString("wsFrameClient.ioe", e));
                    close(e);
                }
            }
        }

        @Override
        public void failed(Throwable exc, Void attachment) {
            if (exc instanceof ReadBufferOverflowException) {
                // response will be empty if this exception is thrown
                response = ByteBuffer.allocate(
                        ((ReadBufferOverflowException) exc).getMinBufferSize());
                response.flip();
                try {
                    processSocketRead();
                } catch (IOException e) {
                    close(e);
                }
            } else {
                close(exc);
            }
        }
    }
}
