package requestHandlers.djonDB;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

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

import org.json.JSONArray;
import org.json.JSONObject;

import requestHandlers.RequestHandler;
import Beans.R2UserBean;
import Util.ReceiptDateComparator;
import Util.ReceiptNumberComparator;
import Util.ReceiptStringComparator;
import Util.djonDBUtil;
import djondb.BSONArrayObj;
import djondb.BSONObj;
import djondb.DjondbConnection;

public class getReceipts2_djon implements RequestHandler{
	private static Map<String, String> ops = new HashMap<String, String>();
	private static Map<String, String> colAlias = new HashMap<String, String>();
	
	static
	{
		ops.put("eq", "="); //equal
		ops.put("ne", "<>");//not equal
		ops.put("lt", "<");//less than
		ops.put("le", "<=");//less than or equal
		ops.put("gt", ">");//greater than
		ops.put("ge", ">=");//greater than or equal
		ops.put("bw", "LIKE");//begins with
		ops.put("bn", "NOT LIKNE");//doesn't begin with
		ops.put("in", "LIKE");//is in
		ops.put("ni", "NOT LIKE");//is not in
		ops.put("ew", "LIKE");//ends with
		ops.put("en", "NOT LIKE");//doesn't end with
		ops.put("cn", "LIKE");// contains
		ops.put("nc", "NOT LIKE");//doesn't contain
		
		colAlias.put("rid", "ReceiptID");
		colAlias.put("item", "ItemName");
		colAlias.put("merchantName", "MerchantName");
		colAlias.put("price", "ItemPrice");
		colAlias.put("qty", "ItemQty");
		colAlias.put("taxRate", "ItemTaxRate");
		colAlias.put("total", "round(ItemPrice*ItemQty*(1+ItemTaxRate), 2)");
		colAlias.put("card", "CardID");
		colAlias.put("date", "PurchaseDate");
	}
	@Override
	public void processRequest(Object user, HttpServletRequest req,
			HttpServletResponse res, Object[] services, Object log)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		PrintWriter out = res.getWriter();
		JSONObject ret = new JSONObject();
		JSONArray rows = new JSONArray();
		ret.put("ret", false);
		ret.put("page", 1);
		ret.put("total", 0);
		ret.put("records", 0);
		ret.put("rows", rows);
		DjondbConnection c;
		try
		{
			HttpSession session = req.getSession(false);
			if(session != null)
			{
				R2UserBean userbean = (R2UserBean)session.getAttribute("currentSessionUser");
				if(userbean != null)
				{
					int page = req.getParameter("page") == null || req.getParameter("page").equals("") ? 1 : Integer.parseInt(req.getParameter("page")); // get the requested page
					int limit = req.getParameter("rows") == null || req.getParameter("rows").equals("") ? 5 : Integer.parseInt(req.getParameter("rows"));
					String sidx = req.getParameter("sidx") == null || req.getParameter("sidx").equals("") ? "date" : req.getParameter("sidx");
					String sord = req.getParameter("sord") == null || req.getParameter("sord").equals("") ? "asc" : req.getParameter("sord");

					/*System.out.println("page = " + req.getParameter("page"));
					System.out.println("limit = " + req.getParameter("rows"));
					System.out.println("sidx = " + req.getParameter("sidx"));
					System.out.println("sord = " + req.getParameter("sord"));*/
					
					// search request
					boolean _search = req.getParameter("_search") == null || req.getParameter("_search").equals("") ? false : Boolean.parseBoolean(req.getParameter("_search"));
					String field = req.getParameter("searchField");
					String oper = req.getParameter("searchOper");
					String str = req.getParameter("searchString");
					
					
					// search string
					StringBuilder sb = new StringBuilder();
					sb.append("$'email' == '").append(userbean.getEmail()).append("'");
					sb.append(" and $'_id' == '").append(userbean.getDocID()).append("'");
					System.out.println(sb.toString());
					//$'email' == 'djiang1@student.gsu.edu' and $'_id' == 'dddac36a-ac7b-4d85-beb5-bc5c94b3a888'
					c = djonDBUtil.openConn();
					
					//BSONArrayObj userArr = c.find(djonDBUtil.DBNAME, djonDBUtil.USERS_COLLECTION_NAME, sb.toString());
					BSONArrayObj userArr = c.find(djonDBUtil.DBNAME, djonDBUtil.USERS_COLLECTION_NAME, "$'email' == 'djiang1@student.gsu.edu' and $'_id' == 'dddac36a-ac7b-4d85-beb5-bc5c94b3a888'");
					if(userArr != null)
					{
						BSONObj userDoc = userArr.get(0);
						BSONArrayObj receiptArr = userDoc.getBSONArray(djonDBUtil.USER_RECEIPTS_FIELDNAME);
						if(receiptArr != null && receiptArr.length() > 0)
						{
							int count = receiptArr.length();
							int total_pages = 1;
							if(count > 0 && limit > 0)
							{
								total_pages = count / limit;
								if(count % limit > 0)
									total_pages++;
							}
							if(page > total_pages)
							{
								page = total_pages;
							}
							int start = limit * page - limit;
							if(start < 0)
							{
								start = 0;
							}
							int end = start + limit;
							if(end > receiptArr.length())
								end = receiptArr.length();
							System.out.println("count = " + count);
							System.out.println("total_pages = " + total_pages);
							System.out.println("page = " + page);
							System.out.println("start = " + start);
							// put it into an array
							BSONObj[] arr = new BSONObj[receiptArr.length()];
							for(int i=0; i<arr.length; ++i)
							{
								arr[i] = receiptArr.get(i);
							}

							System.err.println("sorting " + sidx);
							if(sidx.equals("merchantName"))
							{
								Arrays.sort(arr, new ReceiptStringComparator(sord, djonDBUtil.USER_RECEIPT_MERCHANT_FIELDNAME));
							}
							else if(sidx.equals("total"))
							{
								Arrays.sort(arr, new ReceiptNumberComparator(sord, djonDBUtil.USER_RECEIPT_TOTAL_FIELDNAME));
							}
							else if(sidx.equals("card"))
							{
								Arrays.sort(arr, new ReceiptStringComparator(sord, djonDBUtil.USER_RECEIPT_CARD_FIELDNAME));
							}
							else if(sidx.equals("date"))
							{
								Arrays.sort(arr, new ReceiptDateComparator(sord, djonDBUtil.USER_RECEIPT_PURCHASEDATE_FIELDNAME));
							}
							
							for(int i=start; i<end; ++i)
							{
								//BSONObj receipt = receiptArr.get(i);
								BSONObj receipt = arr[i];
								JSONArray record = new JSONArray();
								record.put(receipt.getInt(djonDBUtil.USER_RECEIPT_ID_FIELDNAME));
								record.put(receipt.getString(djonDBUtil.USER_RECEIPT_MERCHANT_FIELDNAME));
								record.put(djonDBUtil.round(receipt.getDouble(djonDBUtil.USER_RECEIPT_TOTAL_FIELDNAME), 2));
								record.put(receipt.getString(djonDBUtil.USER_RECEIPT_CARD_FIELDNAME));
								record.put(receipt.getString(djonDBUtil.USER_RECEIPT_PURCHASEDATE_FIELDNAME));
								rows.put(record);
							}

							ret.put("page", page);
							ret.put("total", total_pages);
							ret.put("records", count);
							ret.put("rows", rows);
							ret.put("ret", true);
						}
					}
					
					
					/*if(!_search)
					{
						stmt = con.prepareStatement(sql + "GROUP BY R2LineItem.ReceiptID ORDER BY " + sidx + " " + sord);
					}
					else
					{
						stmt = con.prepareStatement(sql + " AND " + getSearchClause(colAlias.get(field), oper, str) + " GROUP BY R2LineItem.ReceiptID ORDER BY " + sidx + " " + sord);
					}*/
				}
			}
		}
		catch (Throwable theException) 	    
		{
			theException.printStackTrace();
		     System.out.println(theException); 
		}
		finally
		{
			/*System.out.println("ret json:");
			System.out.println(ret);*/
			out.print(ret);
			out.close();
		}
	}	
	private String getSearchClause(final String field, final String oper, String val)
	{
		StringBuilder sb = new StringBuilder();
		if(oper.equalsIgnoreCase("bw") || oper.equalsIgnoreCase("bn")) val += "%";
	    if(oper.equalsIgnoreCase("ew") || oper.equalsIgnoreCase("en") ) val = "%" + val;
	    if(oper.equalsIgnoreCase("cn") || oper.equalsIgnoreCase("nc") || oper.equalsIgnoreCase("in") || oper.equalsIgnoreCase("ni")) val = "%" + val + "%";
	    sb.append(" ").
	    append(field).
	    append(" ").
	    append(ops.get(oper)).
	    append(" ");
	    if(isNumeric(val))
	    {
	    	sb.append(val);
	    }
	    else
	    {
	    	sb.append("'").append(val).append("'");
	    }
	    sb.append(" ");
	    return sb.toString();
	}
	private boolean isNumeric(String str)  
	{  
	  try  
	  {  
	    double d = Double.parseDouble(str);  
	  }  
	  catch(NumberFormatException nfe)  
	  {  
	    return false;  
	  }  
	  return true;  
	}
}
