package com.k_int.discover.sru.action;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.k_int.discover.sru.service.SearchDataService;
import com.opensymphony.xwork2.ActionSupport;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;

public abstract class AbstractSearchAction extends ActionSupport implements ServletRequestAware {
  private static final long serialVersionUID = 1L;
  protected HttpServletRequest request;
  private Map<String, String> params = new HashMap<String, String>();
  protected String query;
  protected boolean phrase=false;
  private String landscape;
  
  private SearchDataService service;
  private Long numOfResults = 0l;
  
  private static Logger log   = Logger.getLogger(AbstractSearchAction.class);
  
  public String getSruUrl() {
    StringBuilder sb = new StringBuilder(landscape);
    sb.append("?");
    
    Iterator<Entry<String, String>> param_it = params.entrySet().iterator();
    while (param_it.hasNext()) {
      Entry<String, String> param = param_it.next();
      sb.append(param.getKey());
      sb.append("=");
      sb.append(param.getValue());
    
      if (param_it.hasNext()) sb.append("&"); 
    }
    
    log.debug("Returning sruUrl as: " + sb.toString());
    return sb.toString();
  }

  public void setDataService(SearchDataService dataService) {
	  this.service = dataService;
  }
  
  public SearchDataService getDataService() {
	  return this.service;
  }

  public void setServletRequest(HttpServletRequest request) {
    this.request = request;
  } 
  
  
  protected String getOrDefault(String param, String default_value) {
    String ret = request.getParameter(param);
    return (ret!=null && !ret.trim().equals("")) ? ret : default_value;
  }

  
  public String execute() throws Exception 
  {
      String result = ERROR;  
      //String submit = request.getParameter("pageSubmitted");
    
      if (request.getMethod().equals("POST")) 
      {
          landscape = getOrDefault("landscape", "default");

          addOrDrop("version", "1.1");
          addOrDrop("operation", "searchRetrieve");
          addOrDrop("startRecord", "1");
          addOrDrop("maximumRecords", "10");
          addOrDrop("stylesheet", null);
      
          // special case - needs to be dealt with in extending classes and escaped. 
          query = getOrDefault("query", "*");
      
      //fix this
      
      
      
      
      //Remove any 'special' characters from the query so that we don't break things
      if ( query.contains("\"") ) 
      {
          query=query.trim();
          if(query.indexOf("\"")==0 && query.lastIndexOf("\"")==query.length()-1)
              phrase=true;
          
    	  query = query.replaceAll("\"", " ");
      }
      if ( query.contains("'") ) 
      {
          if(phrase==false && query.indexOf("'")==0 && query.lastIndexOf("'")==query.length()-1)
              phrase=true;
    	  
          query = query.replaceAll("'", " ");
      }
      
      
      
     // int double_quote_index = query.indexOf("\"");
     // int single_quote_index = query.indexOf("'");

      if ( query != null ) {
    	  query = URLEncoder.encode(query, "UTF-8");
      }
      
      result = internalExecute();
      
      if (query!=null) 
      {
    	  params.put("query", query);
      }
    } 
    else 
    {
    	// Coming to the page for the first time
    	log.debug("Loading a search front page");
//    	this.numOfResults = service.getTotalNumOfResourcesFromDB();
    	this.numOfResults = service.getTotalNumOfResourcesFromSolr();
    	internalSetupPage();
    }
    
    return result;
  }
  
  
  private void addOrDrop(String key, String default_value) {
    String value = getOrDefault(key, default_value);
    if (value!=null) {
      params.put(key, value);
    }
  }


  public Long getNumOfResults() {
	  log.debug("getNumOfResults called! value: " + this.numOfResults);
	  return this.numOfResults;
  }
  
  protected abstract String internalExecute() throws Exception;
  protected abstract void internalSetupPage() throws Exception;

}