//
//  ========================================================================
//  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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;

public class ClientGenerator extends Generator
{
    // To keep the algorithm simple, and given that the max length of a
    // frame is 0xFF_FF we allow the max length of a name (or value) to be
    // 0x7F_FF - 4 (the 4 is to make room for the name (or value) length).
    public static final int MAX_PARAM_LENGTH = 0x7F_FF - 4;

    public ClientGenerator(ByteBufferPool byteBufferPool)
    {
        super(byteBufferPool);
    }

    public Result generateRequestHeaders(int request, HttpFields fields, Callback callback)
    {
        request &= 0xFF_FF;

        final Charset utf8 = StandardCharsets.UTF_8;
        List<byte[]> bytes = new ArrayList<>(fields.size() * 2);
        int fieldsLength = 0;
        for (HttpField field : fields)
        {
            String name = field.getName();
            byte[] nameBytes = name.getBytes(utf8);
            if (nameBytes.length > MAX_PARAM_LENGTH)
                throw new IllegalArgumentException("Field name " + name + " exceeds max length " + MAX_PARAM_LENGTH);
            bytes.add(nameBytes);

            String value = field.getValue();
            byte[] valueBytes = value.getBytes(utf8);
            if (valueBytes.length > MAX_PARAM_LENGTH)
                throw new IllegalArgumentException("Field value " + value + " exceeds max length " + MAX_PARAM_LENGTH);
            bytes.add(valueBytes);

            int nameLength = nameBytes.length;
            fieldsLength += bytesForLength(nameLength);

            int valueLength = valueBytes.length;
            fieldsLength += bytesForLength(valueLength);

            fieldsLength += nameLength;
            fieldsLength += valueLength;
        }

        // Worst case FCGI_PARAMS frame: long name + long value - both of MAX_PARAM_LENGTH
        int maxCapacity = 4 + 4 + 2 * MAX_PARAM_LENGTH;

        // One FCGI_BEGIN_REQUEST + N FCGI_PARAMS + one last FCGI_PARAMS

        ByteBuffer beginRequestBuffer = byteBufferPool.acquire(16, false);
        BufferUtil.clearToFill(beginRequestBuffer);
        Result result = new Result(byteBufferPool, callback);
        result = result.append(beginRequestBuffer, true);

        // Generate the FCGI_BEGIN_REQUEST frame
        beginRequestBuffer.putInt(0x01_01_00_00 + request);
        beginRequestBuffer.putInt(0x00_08_00_00);
        // Hardcode RESPONDER role and KEEP_ALIVE flag
        beginRequestBuffer.putLong(0x00_01_01_00_00_00_00_00L);
        BufferUtil.flipToFlush(beginRequestBuffer, 0);

        int index = 0;
        while (fieldsLength > 0)
        {
            int capacity = 8 + Math.min(maxCapacity, fieldsLength);
            ByteBuffer buffer = byteBufferPool.acquire(capacity, true);
            BufferUtil.clearToFill(buffer);
            result = result.append(buffer, true);

            // Generate the FCGI_PARAMS frame
            buffer.putInt(0x01_04_00_00 + request);
            buffer.putShort((short)0);
            buffer.putShort((short)0);
            capacity -= 8;

            int length = 0;
            while (index < bytes.size())
            {
                byte[] nameBytes = bytes.get(index);
                int nameLength = nameBytes.length;
                byte[] valueBytes = bytes.get(index + 1);
                int valueLength = valueBytes.length;

                int required = bytesForLength(nameLength) + bytesForLength(valueLength) + nameLength + valueLength;
                if (required > capacity)
                    break;

                putParamLength(buffer, nameLength);
                putParamLength(buffer, valueLength);
                buffer.put(nameBytes);
                buffer.put(valueBytes);

                length += required;
                fieldsLength -= required;
                capacity -= required;
                index += 2;
            }

            buffer.putShort(4, (short)length);
            BufferUtil.flipToFlush(buffer, 0);
        }


        ByteBuffer lastParamsBuffer = byteBufferPool.acquire(8, false);
        BufferUtil.clearToFill(lastParamsBuffer);
        result = result.append(lastParamsBuffer, true);

        // Generate the last FCGI_PARAMS frame
        lastParamsBuffer.putInt(0x01_04_00_00 + request);
        lastParamsBuffer.putInt(0x00_00_00_00);
        BufferUtil.flipToFlush(lastParamsBuffer, 0);

        return result;
    }

    private int putParamLength(ByteBuffer buffer, int length)
    {
        int result = bytesForLength(length);
        if (result == 4)
            buffer.putInt(length | 0x80_00_00_00);
        else
            buffer.put((byte)length);
        return result;
    }

    private int bytesForLength(int length)
    {
        return length > 127 ? 4 : 1;
    }

    public Result generateRequestContent(int request, ByteBuffer content, boolean lastContent, Callback callback)
    {
        return generateContent(request, content, false, lastContent, callback, FCGI.FrameType.STDIN);
    }
}
