package com.telephoners.krakyournet.ctf.beans.tasks;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.telephoners.krakyournet.ctf.beans.Flag;
import com.telephoners.krakyournet.ctf.helpers.StreamUtils;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.mongodb.morphia.annotations.Entity;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Entity("tasks")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class WebTask extends Task
{
    private String url;

    public WebTask(String name, int level, String description, List<Flag> flags, String url)
    {
        super(name, level, description, flags);
        this.url = url;
    }

    public WebTask()
    {
    }

    //todo: avoid converting in both ways
    private Map<String, String> buildHeadersMap(Header[] headers) {
       return Stream.of(headers)
               .collect(Collectors.toMap(
                       Header::getName,
                       Header::getValue
               ));
    }

    private Header[] buildHeadersArray(Map<String, String> headers) {
        List<BasicHeader> headersList = headers.entrySet().stream() //todo: dirty casting
                .map(headerEntry -> new BasicHeader(headerEntry.getKey(), headerEntry.getValue()))
                .collect(Collectors.toList());
        Header[] headersArray = new Header[headersList.size()];
        return headersList.toArray(headersArray);
    }

    @Override
    public TaskResponse getTaskResponse(TaskRequestContext taskRequestContext) throws IOException
    {
        String url = getUrl() + taskRequestContext.getPath();
        CloseableHttpResponse response = proxyRequest(url, taskRequestContext.getHeaders());
        String text = StreamUtils.readStream(response.getEntity().getContent());
        return new TaskResponse(text, buildHeadersMap(response.getAllHeaders()));
    }

    public String getUrl()
    {
        return url;
    }

    public void setUrl(String url)
    {
        this.url = url;
    }

    private CloseableHttpResponse proxyRequest(String url, Map<String, String> headers) throws IOException
    {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet(url);
        httpget.setHeaders(buildHeadersArray(headers));
        return httpClient.execute(httpget);
    }
}
