//
//  ========================================================================
//  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.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;

        Charset utf8 = Charset.forName("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);

        buffer.flip();

        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);
        endRequestBuffer.flip();
        return endRequestBuffer;
    }
}
