//
//  ========================================================================
//  Copyright (c) 1995-2019 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.http2.hpack;

import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.nio.ByteBuffer;
import java.util.Map;

import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ajax.JSON;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;


public class HpackPerfTest
{
    int _maxDynamicTableSize=4*1024;
    int _unencodedSize;
    int _encodedSize;
    
    @BeforeEach
    public void before()
    {
        _unencodedSize=0;
        _encodedSize=0;
    }

    @AfterEach
    public void after()
    {        
        System.err.printf("dynamictable=%d unencoded=%d encoded=%d p=%3.1f%%%n",_maxDynamicTableSize,_unencodedSize,_encodedSize,100.0*_encodedSize/_unencodedSize);

    }
    
    @Test
    public void simpleTest() throws Exception
    {
        runStories(_maxDynamicTableSize);
    }
    
    private void runStories(int maxDynamicTableSize) throws Exception
    {
        // Find files
        File data = MavenTestingUtils.getTestResourceDir("data");
        String[] files = data.list(new FilenameFilter()
        {
            @Override
            public boolean accept(File dir, String name)
            {
                return name.startsWith("story_");
            }
        });
        
        // Parse JSON
        Map<String,Object>[] stories = new Map[files.length];
        int i=0;
        for (String story : files)
            stories[i++]=(Map<String,Object>)JSON.parse(new FileReader(new File(data,story)));
        
        ByteBuffer buffer = BufferUtil.allocate(256*1024);
        
        // Encode all the requests
        encodeStories(buffer,stories,"request");

        // clear table
        BufferUtil.clearToFill(buffer);
        BufferUtil.flipToFlush(buffer,0);
        
        // Encode all the responses
        encodeStories(buffer,stories,"response");
        
    }
    
    private void encodeStories(ByteBuffer buffer,Map<String,Object>[] stories, String type) throws Exception
    {
        for (Map<String,Object> story : stories)
        {
            if (type.equals(story.get("context")))
            {
                HpackEncoder encoder = new HpackEncoder(_maxDynamicTableSize,_maxDynamicTableSize);
                
                // System.err.println(story);
                Object[] cases = (Object[])story.get("cases");
                for (Object c : cases)
                {
                    // System.err.println("  "+c);
                    Object[] headers = (Object[])((Map<String,Object>)c).get("headers");
                    // System.err.println("    "+headers);
                    HttpFields fields = new HttpFields();
                    for (Object header:headers)
                    {
                        Map<String,String> h = (Map<String,String>)header;
                        Map.Entry<String, String> e = h.entrySet().iterator().next();
                        fields.add(e.getKey(),e.getValue());
                        _unencodedSize+=e.getKey().length()+e.getValue().length();
                        
                    }

                    BufferUtil.clearToFill(buffer);
                    encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
                    BufferUtil.flipToFlush(buffer,0);
                    _encodedSize+=buffer.remaining();
                    
                }
            }
        }

    }
    
    
}
