import aaz.libhpsocket.helper.headers;
import aaz.libhpsocket.helper.websocket;
import aaz.libhpsocket.helper.cookie;
import aaz.libhpsocket.properties.tcpServer;

var wsHelper =  aaz.libhpsocket.helper.websocket;
var realloc = raw.realloc;
var _dll = aaz.libhpsocket._dll;

namespace aaz.libhpsocket.properties.httpServer{
    ..table.assign(self, ..aaz.libhpsocket.properties.tcpServer);
    
	getUrl = function(path, scheme){
		var ip, port = owner.getListenAddress();
		if( !(ip&&port) ) return ;
		if( ip=="0.0.0.0" )ip = "localhost";
		var url = ..string.format("%s://%s:%d", scheme:"http", ip, port); 
		if(path){
			path = ..string.replace(path, "\\", "/");
			if(path[1]!='/'#) path= "/" + path;
			return url + path;
		}
		return url;
	}
	getWsUrl = function(path){
		return owner.getUrl(path, "ws");
	}
	
	getWsSecAccept = function(connId){
		var ok, key = owner.getHeader(connId, "Sec-WebSocket-Key"); 
		if(key) return wsHelper.getSecAccept(key); 
	}
	
	getWsSecProtocol = function(connId){
		var ok, protocol = owner.getHeader(connId, "Sec-WebSocket-Protocol");
		if(protocol) return ..string.split(protocol, "<, >");
		return {};
	}
	
	sendSwitchingProtocols = function(connId, headers){
		return owner.sendResponse(connId, null, headers, 101/*HSC_SWITCHING_PROTOCOLS*/, null)	
	}
	
	sendWsSwitchingProtocols = function(connId, headers, protocol){
		headers = ..aaz.libhpsocket.helper.headers(headers);
		
		headers.mixin({
			["Connection"] = "Upgrade";
			["Upgrade"] = "websocket";
			["Sec-WebSocket-Accept"] = owner.getWsSecAccept(connId);
			["Sec-WebSocket-Protocol"] = protocol : owner.getWsSecProtocol(connId)[1];
		})

		return owner.sendResponse(connId,null,headers,101/*HSC_SWITCHING_PROTOCOLS*/,null)	
	}

	sendResponse = function(connId,body, headers, statusCode=200, lpszDesc){
		headers = ..aaz.libhpsocket.helper.headers(headers);
		return _dll.HP_HttpServer_SendResponseB(owner.pSocket, connId, statusCode, lpszDesc, headers.struct(), headers.length(), body, #body);
	}
	
	sendLocalFile = function(connId, filename, statusCode=200, desc, headers){
		headers = ..aaz.libhpsocket.helper.headers(headers)
		return _dll.HP_HttpServer_SendLocalFileB(owner.pSocket,connId,..io.fullpath(filename),statusCode,desc,headers,headers.length());
	}

	sendChunkData = function(connID, pData, len=0, extensions){
		return _dll.HP_HttpServer_SendChunkDataB(connID, pData, len, extensions); 
	}

	sendWsMessage = function(connId, data, opCode, final=true, bodyLen=0, reserved){
		var len;
		if( data[["_struct"]] ){
			len = ..raw.sizeof(data);
			opCode = 2;
		}
		elseif( type(data) == type.string ){
			len = #data;
			opCode = 1;
		}
		else {
			error("sendWsMessage 参数2 data 格式有误",2)
		}
		
    	var pData = realloc(len,,data); 
		var r = _dll.HP_HttpServer_SendWSMessageB( owner.pSocket, connId, final, reserved, opCode, pData, len, ..math.size64(len + bodyLen) );
		realloc(0, pData);
		return r;
	}

	release = function( connId ){
		return _dll.HP_HttpServer_ReleaseB( owner.pSocket,connId );
	}

	getUrlFieldSet = function(connId){
		return 0xFFFF & _dll.HP_HttpServer_GetUrlFieldSet(owner.pSocket,connId);
	} 

	getUrlField = function(connId,enField){
		var s = _dll.HP_HttpServer_GetUrlFieldP(owner.pSocket,connId,enField);
		if(s) return ..raw.str(s);
	}

	getMethod = function(connId){
		var p = _dll.HP_HttpServer_GetMethodP(owner.pSocket,connId);
		if( p ) return ..raw.str(s);
	}

	getRequestUri = function(connId){	
		var fileds = _dll.HP_HttpServer_GetUrlFieldSet(owner.pSocket,connId);
		var uri = "/"
		if(fileds & (1<<3) ) uri  = owner.getUrlField(connId,3/*HUF_PATH*/);
		if(fileds & (1<<4) ) uri  = uri + "?" + owner.getUrlField(connId,4/*HUF_QUERY*/);
		return uri;
	}

	isUpgrade = function(connId){
		return _dll.HP_HttpServer_IsUpgradeB(owner.pSocket,connId);
	}

	isKeepAlive = function(connId){
		return _dll.HP_HttpServer_IsKeepAliveB(owner.pSocket,connId);
	}

	getVersion = function(){
		return 0xFFFF & _dll.HP_HttpServer_GetVersion(owner.pSocket);
	}

	getHost = function(connId){
		var p = _dll.HP_HttpServer_GetHostP(owner.pSocket,connId);
		if(p) return ..raw.str(p);
	}

	getContentLength = function(connId){
		return _dll.HP_HttpServer_GetContentLength(owner.pSocket,connId);
	}

	getContentType = function(connId){
		var p = _dll.HP_HttpServer_GetContentTypeP(owner.pSocket,connId);
		if(p) return ..raw.str(p);
	}

	getContentEncoding = function(connId){
		var p = _dll.HP_HttpServer_GetContentEncodingP(owner.pSocket,connId);
		if(p) return ..raw.str(p);
	}

	getTransferEncoding = function(connId){
		var p = _dll.HP_HttpServer_GetTransferEncodingP(owner.pSocket,connId);
		if(p) return ..raw.str(p);
	}

	getUpgradeType = function(connId){
		return  _dll.HP_HttpServer_GetUpgradeType(owner.pSocket,connId);
	}

	getParseErrorCode = function(connId){
		var errdesc= {string value};
		var errno = 0xFFFF & _dll.HP_HttpServer_GetParseErrorCode(owner.pSocket,connId,errdesc);
		return errno,errdesc.value;
	}

	getHeader = function(connId,name){
		var s = {string value};
		return _dll.HP_HttpServer_GetHeaderB(owner.pSocket,connId,name,s), s.value;
	}

	getHeaders = function(connId,name){
		var s = {string array[] = {INT length} };
		_dll.HP_HttpServer_GetHeaders( owner.pSocket,connId, name, null, s.array);
		if( s.array.length == 0 ){
			return true, s.array; 
		}
		
		return _dll.HP_HttpServer_GetHeadersB( owner.pSocket,connId, name, s, s.array),  s.array;
	}

	getAllHeaders = function(connId){
		var hdrs = ..aaz.libhpsocket.helper.headers(); 
		_dll.HP_HttpServer_GetAllHeaders(owner.pSocket,connId,null,hdrs.array)
		if( hdrs.array.length == 0 ){
			return true, hdrs.array; 
		}
		
		return _dll.HP_HttpServer_GetAllHeaders(owner.pSocket,connId,hdrs.struct(),hdrs.array), hdrs.array;
	}

	getAllHeaderNames = function(connId){
		var s = {string array[] = {INT length} };
		_dll.HP_HttpServer_GetAllHeaderNames(owner.pSocket,connId,null,s.array);
		if( s.array.length == 0 ){
			return true, s.array; 
		}
		
		return _dll.HP_HttpServer_GetAllHeaderNames(owner.pSocket,connId,s,s.array),  s.array;
	}

	getCookie = function(connId,name){
		var s = {string value};
		return _dll.HP_HttpServer_GetCookie(owner.pSocket,connId,name,s), s.value;
	}

	getAllCookies = function(connId){
		var cookies = ..aaz.libhpsocket.helper.cookie();
		_dll.HP_HttpServer_GetAllCookies(owner.pSocket,connId,null,cookies.array);
		if( cookies.array.length == 0 ){
			return true, cookies.array; 
		}
		return _dll.HP_HttpServer_GetAllCookies(owner.pSocket,connId,cookies,cookies.array), cookies.array;
	}

	getWsMessageState = function(connId){
		var final = {bool value}
		var reserved = {BYTE value}
		var opCode = {BYTE value}
		var mask = {INT value}
		var bodyLen = {LONG value}
		var bodyRemain = {LONG value} 
		
		if( _dll.HP_HttpServer_GetWSMessageState(owner.pSocket,connId,final,reserved ,opCode,mask,bodyLen,bodyRemain ) ){
			return{
				final = final.value;
				reserved = reserved.value;
				opCode = opCode.value;
				mask = mask.value;
				bodyLen = bodyLen.value;
				bodyRemain = bodyRemain.value;
			}
		}
	}

	releaseDelay = {
    	_get = function(){
    		return _dll.HP_HttpServer_GetReleaseDelay(owner.pSocket); 
    	}
    	
    	_set = function(v){
    		_dll.HP_HttpServer_SetReleaseDelay(owner.pSocket, v);
    	} 
	} 

	localVersion = {
    	_get = function(){
    		return _dll.HP_HttpServer_GetLocalVersion(owner.pSocket); 
    	}
    	
    	_set = function(v){
    		_dll.HP_HttpServer_SetLocalVersion(owner.pSocket, v);
    	} 
	}

	isHttpAutoStart = {
    	_get = function(){
    		return _dll.HP_HttpServer_IsHttpAutoStartB(owner.pSocket); 
    	}
    	
    	_set = function(v){
    		_dll.HP_HttpServer_SetHttpAutoStart(owner.pSocket, v);
    	} 
	}	
}
