package dev.peerat.framework;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import dev.peerat.framework.utils.json.Json;
import dev.peerat.framework.utils.json.JsonParser;

public class HttpReader{
	
	private static Pattern HEADER_PATTERN = Pattern.compile("^([^:]*):\\s+(.*)$");
	static JsonParser JSON_PARSER = new JsonParser();

	private Socket socket;
	private InputStream in;
	private BufferedReader reader;
	
	private Map<String, String> headers;

	public HttpReader(Socket socket) throws Exception{
		this.socket = socket;
		this.in = socket.getInputStream();
		this.reader = new BufferedReader(new InputStreamReader(in));
		this.headers = new HashMap<>();
	}
	
	public HttpReader(HttpReader origin) throws Exception{
		this.socket = origin.socket;
		this.in = origin.in;
		this.reader = origin.reader;
	}
	
	HttpReader(InputStream in){
		this.in = in;
		this.reader = new BufferedReader(new InputStreamReader(in));
	}
	
	public boolean isClosed(){
		return this.socket.isClosed();
	}

	void readHeaders() throws Exception{
		String line;
		while(((line = reader.readLine()) != null) && (line.length() > 0)){
			Matcher matcher = HEADER_PATTERN.matcher(line);
			matcher.matches();
			this.headers.put(matcher.group(1).toLowerCase(), matcher.group(2));
		}
	}
	
	public String getHeader(String key){
		return this.headers.get(key.toLowerCase());
	}
	
	public int read(byte[] buffer) throws IOException{
		return this.in.read(buffer);
	}

	public int read(char[] buffer) throws IOException{
		return this.reader.read(buffer);
	}

	public String readLine() throws IOException{
		return this.reader.readLine();
	}

	public boolean ready() throws IOException{
		return this.reader.ready();
	}

	public int readInt() throws Exception{
		int result = 0;
		result += this.in.read() << 24;
		result += this.in.read() << 16;
		result += this.in.read() << 8;
		result += this.in.read();
		return result;
	}
	
	public <J extends Json> J readJson() throws Exception{
		int length = Integer.parseInt(getHeader("content-length"));
		//to limit
		char[] content = new char[length];
		read(content);
		return JSON_PARSER.parse(new String(content));
	}
	
	/*
	 * 
------WebKitFormBoundaryNUjiLBAMuX2dhxU7
Content-Disposition: form-data; name="answer"

12
------WebKitFormBoundaryNUjiLBAMuX2dhxU7
Content-Disposition: form-data; name="filename"

webpack.js
------WebKitFormBoundaryNUjiLBAMuX2dhxU7
Content-Disposition: form-data; name="code_file"; filename="webpack.js"
Content-Type: text/javascript


------WebKitFormBoundaryNUjiLBAMuX2dhxU7--
	 * 
	 */
	
	public List<String> readMultiPartData() throws Exception{
		List<String> list = new ArrayList<>();
		String boundary = getHeader("content-type");
		if(boundary == null) return list;
		boundary = boundary.split(";")[1].split("=")[1];
		readLine();
		
		while(ready()){
			String line;
			while (((line = readLine()) != null) && (line.length() > 0));
			String buffer = "";
			while (((line = readLine()) != null) && (!line.startsWith("--"+boundary))){
				buffer += line+"\n";
			}
			if(buffer.length() < 1) buffer = "\n";
			list.add(buffer.substring(0, buffer.length()-1));
		}

		return list;
	}
}