/**
 *  Query
 *  Copyright 19.05.2016 by Michael Peter Christen, @0rb1t3r
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *  
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program in the file lgpl21.txt
 *  If not, see <http://www.gnu.org/licenses/>.
 */


package org.loklak.server;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Enumeration;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.loklak.LoklakServer;
import org.loklak.data.DAO;
import org.loklak.http.AccessTracker;
import org.loklak.http.RemoteAccess;
import org.loklak.tools.DateParser;

public class Query {
    
    private HttpServletRequest request;
    private Map<String, String> qm;
    public AccessTracker.Track track;
    
    public Query(final HttpServletRequest request) {
        this.qm = new HashMap<>();
        this.request = request;

        // Add request parameters from servlet request
        Enumeration<String> keysEnum = request.getParameterNames();

        while (keysEnum.hasMoreElements()) {
            String key = keysEnum.nextElement();
            qm.put(key, request.getParameter(key));
        }

        // discover remote host
        String clientHost = request.getRemoteHost();
        String XRealIP = request.getHeader("X-Real-IP");
        if (XRealIP != null && XRealIP.length() > 0) clientHost = XRealIP; // get IP through nginx config "proxy_set_header X-Real-IP $remote_addr;"
        
        // start tracking: get calling thread and start tracking for that
        this.track = DAO.access.startTracking(request.getServletPath(), clientHost, request.getHeader("Referer"));
        this.track.setTimeSinceLastAccess(this.track.getDate().getTime() - RemoteAccess.latestVisit(request.getServletPath(), clientHost));
        this.track.setDoSBlackout(LoklakServer.blacklistedHosts.contains(clientHost) || (!this.track.isLocalhostAccess() && (this.track.getTimeSinceLastAccess() < DAO.getConfig("DoS.blackout", 100))));
        this.track.setDoSServicereduction(!this.track.isLocalhostAccess() && (this.track.getTimeSinceLastAccess() < DAO.getConfig("DoS.servicereduction", 1000)));
        this.track.setQuery(qm);
    }
    public void finalize() {
        this.track.finalize();
    }
    public void initGET(final Map<String, String> qm) {
        for (String key : qm.keySet())
            qm.put(key, qm.get(key));
    }
    // initPOST is deprecated because the purpose of it has been replaced by the constructor
    @Deprecated
    public void initPOST(final Map<String, byte[]> map) {
        // This method does nothing, removing it is a bad idea because it can break
        // other servlets / services
    }
    public String getClientHost() {
        return this.track.getClientHost();
    }
    public boolean isLocalhostAccess() {
        return this.track.isLocalhostAccess();
    }
    public long getAccessTime() {
        return this.track.getDate().getTime();
    }
    public long getTimeSinceLastAccess() {
        return this.track.getTimeSinceLastAccess();
    }
    public boolean isDoS_blackout() {
        return this.track.isDoSBlackout();
    }
    public boolean isDoS_servicereduction() {
        return this.track.isDoSServicereduction();
    }
    public void recordEvent(String eventName, Object eventValue) {
        this.track.put(AccessTracker.EVENT_PREFIX + eventName, eventValue);
    }
    public String get(String key, String dflt) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null ? dflt : val;
    }
    public String[] get(String key, String[] dflt, String delim) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null || val.length() == 0 ? dflt : val.split(delim);
    }
    public int get(String key, int dflt) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null || val.length() == 0 ? dflt : Integer.parseInt(val);
    }
    public long get(String key, long dflt) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null || val.length() == 0 ? dflt : Long.parseLong(val);
    }
    public double get(String key, double dflt) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null || val.length() == 0 ? dflt : Double.parseDouble(val);
    }
    public boolean get(String key, boolean dflt) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        return val == null ? dflt : "true".equals(val) || "1".equals(val);
    }
    public Date get(String key, Date dflt, int timezoneOffset) {
        String val = qm == null ? request.getParameter(key) : qm.get(key);
        try {
            return val == null || val.length() == 0 ? dflt : DateParser.parse(val, timezoneOffset).getTime();
        } catch (ParseException e) {
            return dflt;
        }
    }
    public Set<String> getKeys() {
        return request.getParameterMap().keySet();
    }
    public void setResponse(final HttpServletResponse response, final String mime) {
        long access_time = this.getAccessTime();
        response.setDateHeader("Last-Modified", access_time);
        response.setDateHeader("Expires", access_time + 2 * DAO.getConfig("DoS.servicereduction", 1000));
        response.setContentType(mime);
        response.setHeader("X-Robots-Tag",  "noindex,noarchive,nofollow,nosnippet");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
    }
    public int hashCode() {
        return qm.hashCode();
    }

    public HttpServletRequest getRequest(){ return this.request; }
}
@@ -2933,17 +2933,16 @@
 tring%3E q
-m
 ) %7B%0A    
@@ -2949,59 +2949,45 @@
     
-for (String key : qm.keySet())%0A            
+q.keySet().forEach(k -%3E this.
 qm.put(k
 ey, 
@@ -2986,22 +2986,18 @@
 ut(k
-ey
 , q
-m
 .get(k
-ey
+)
 ));%0A

fix initGet