//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.fcgi.generator;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;

public class ServerGenerator extends Generator
{
    private static final byte[] STATUS = new byte[]{'S', 't', 'a', 't', 'u', 's'};
    private static final byte[] COLON = new byte[]{':', ' '};
    private static final byte[] EOL = new byte[]{'\r', '\n'};

    private final boolean sendStatus200;

    public ServerGenerator(ByteBufferPool byteBufferPool)
    {
        this(byteBufferPool, true);
    }

    public ServerGenerator(ByteBufferPool byteBufferPool, boolean sendStatus200)
    {
        super(byteBufferPool);
        this.sendStatus200 = sendStatus200;
    }

    public Result generateResponseHeaders(int request, int code, String reason, HttpFields fields, Callback callback)
    {
        request &= 0xFF_FF;

        final Charset utf8 = StandardCharsets.UTF_8;
        List<byte[]> bytes = new ArrayList<>(fields.size() * 2);
        int length = 0;

        if (code != 200 || sendStatus200)
        {
            // Special 'Status' header
            bytes.add(STATUS);
            length += STATUS.length + COLON.length;
            if (reason == null)
                reason = HttpStatus.getMessage(code);
            byte[] responseBytes = (code + " " + reason).getBytes(utf8);
            bytes.add(responseBytes);
            length += responseBytes.length + EOL.length;
        }

        // Other headers
        for (HttpField field : fields)
        {
            String name = field.getName();
            byte[] nameBytes = name.getBytes(utf8);
            bytes.add(nameBytes);

            String value = field.getValue();
            byte[] valueBytes = value.getBytes(utf8);
            bytes.add(valueBytes);

            length += nameBytes.length + COLON.length;
            length += valueBytes.length + EOL.length;
        }
        // End of headers
        length += EOL.length;

        final ByteBuffer buffer = byteBufferPool.acquire(length, true);
        BufferUtil.clearToFill(buffer);

        for (int i = 0; i < bytes.size(); i += 2)
            buffer.put(bytes.get(i)).put(COLON).put(bytes.get(i + 1)).put(EOL);
        buffer.put(EOL);

        BufferUtil.flipToFlush(buffer, 0);

        return generateContent(request, buffer, true, false, callback, FCGI.FrameType.STDOUT);
    }

    public Result generateResponseContent(int request, ByteBuffer content, boolean lastContent, boolean aborted, Callback callback)
    {
        if (aborted)
        {
            Result result = new Result(byteBufferPool, callback);
            if (lastContent)
                result.append(generateEndRequest(request, true), true);
            else
                result.append(BufferUtil.EMPTY_BUFFER, false);
            return result;
        }
        else
        {
            Result result = generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDOUT);
            if (lastContent)
                result.append(generateEndRequest(request, false), true);
            return result;
        }
    }

    private ByteBuffer generateEndRequest(int request, boolean aborted)
    {
        request &= 0xFF_FF;
        ByteBuffer endRequestBuffer = byteBufferPool.acquire(8, false);
        BufferUtil.clearToFill(endRequestBuffer);
        endRequestBuffer.putInt(0x01_03_00_00 + request);
        endRequestBuffer.putInt(0x00_08_00_00);
        endRequestBuffer.putInt(aborted ? 1 : 0);
        endRequestBuffer.putInt(0);
        BufferUtil.flipToFlush(endRequestBuffer, 0);
        return endRequestBuffer;
    }
}
