/*******************************************************************************
 * Copyright 2012 Relay Technology Management, Inc.
 * 
 * Licensed under the Relay Technology Management, Inc. License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may request a copy of the License at
 * 
 * support@relaytm.com
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.relay.winter.server;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.attivio.messages.QueryRequest;
import com.attivio.messages.QueryRequest.SynonymsMode;
import com.attivio.messages.QueryResponse;
import com.attivio.model.AttivioException;
import com.attivio.model.query.Query;
import com.attivio.model.request.FacetBucket;
import com.attivio.model.request.FacetRequest;
import com.attivio.model.request.FacetRequest.SortBy;
import com.attivio.model.request.FacetResponse;
import com.attivio.model.request.Sort.SortOrder;
import com.isomorphic.criteria.AdvancedCriteria;
import com.isomorphic.criteria.Criterion;
import com.isomorphic.criteria.criterion.AndCriterion;
import com.isomorphic.criteria.criterion.CustomCriterion;
import com.isomorphic.criteria.criterion.SimpleCriterion;
import com.isomorphic.datasource.DSRequest;
import com.isomorphic.datasource.DSResponse;

public class NewAttivioFacetCountDataSource extends AbstractAttivioDataSource {
  private static final long serialVersionUID = 1L;
  int MAX_COUNT = 10000000;

  @Override
  public DSResponse executeFetch(DSRequest req) throws Exception {
    List records = fetchRecords(req.getAdvancedCriteria());
    DSResponse dsr = new DSResponse();
    if (records == null) {
      dsr.setTotalRows(0);
      dsr.setStartRow(0);
      dsr.setEndRow(0);
      return dsr;
    }
    
    dsr.setData(records);
    dsr.setTotalRows(records.size());
    dsr.setStartRow(0);
    dsr.setEndRow(records.size());
    
    // System.out.println("FacetDataSrc: response size: " + Long.toString(dsr.getTotalRows()) + " records ");
    
    dsr.setDataSource(this);
    return dsr;
  }

  // Reference:
  // developer.attivio.com/display/extranet310/Facets#Facets-FilteringResultsusingaFacet
  //


  private List fetchRecords(AdvancedCriteria criteria) {
    List<Map<String, Object>> res = new ArrayList<Map<String, Object>>();
    try {
      String strSecondaryIContainsValue = null;
      String facet = (String) criteria.getFieldValue("facet");
      FacetRequest facetRequest = new FacetRequest(facet);
      facetRequest.setFacetFinder(false);
      facetRequest.setSortOrder(SortBy.COUNT, SortOrder.DESCENDING);

      Long maxBucketsStr = (Long) criteria.getFieldValue("maxbuckets");
      facetRequest.setMaxBuckets(maxBucketsStr != null ? maxBucketsStr.intValue() : null);

      AndCriterion crit = new AndCriterion();
      List<Criterion> critters = new ArrayList<Criterion>();
      AndCriterion andCrit = (AndCriterion) criteria.asCriterion();

      // TODO: for some reason the criteria is not making here no matter what I do!!
      // criteria does make it to attiviofacetdatasource.java which is what this is modeled on.
      
      // perhaps really wanted smart gwt advanced cr
      //
      //
      
      for (Criterion c : andCrit.getCriteria()) {
        // ignore debugging criteria that only seem to be set in Chrome browser plugin
        if (c instanceof CustomCriterion) {
          CustomCriterion t = (CustomCriterion) c;
          if (t.getFieldName() == null || "__gwt_ObjectId".equals(t.getFieldName()))
            continue;
        }
        if (c instanceof SimpleCriterion) { 
          SimpleCriterion sc = (SimpleCriterion) c;
          String name = sc.getFieldName();
          if (name.equals("__gwt_ObjectId")) continue;
          // filter out the facet, maxbuckets criteria - leaving the remaining criteria only
          if (name.equals("facet") || 
              name.equals("maxbuckets") ) continue;
          // See if can extract the iContains that seems to come from the filter box so can filter on facets after the fact
          // not the best idea one has had but seems possible
          // System.out.println("Fieldname = " + name);          
          String op = sc.getOperatorId();
          // System.out.println("op = " + op);
          if (op.equals("iContains")) {
            Object o = sc.getValue();
            if (o instanceof String) {
              strSecondaryIContainsValue = (String) o;
              // System.out.println("value type " + strSecondaryIContainsValue);
              continue;
            }
          }
        }
        // TODO: take out the IContains criteria! and apply it AFTER we get the facets back below
        // this might give us what we want.
        //
        critters.add(c);
      }

      System.out.println(critters);
      Query query = null;
      if (critters.size() > 0) {
        crit.setCriteria(critters);
        query = getExpressionFromAndCriterion(crit);
        //System.out.println(query.toString());
      } else {
        //query = new MatchAll(); // new Context("*", "*");
        query = null;
        return null;
      }


      // System.out.println("AIE Query: " + query.toString());
      QueryRequest request = new QueryRequest(query);
      request.setSynonymsMode(SynonymsMode.ON);
      // request.addFilter(facet + ":" + value)
      request.addFacet(facetRequest); // Add to query request

      // This is the call to AIE
      QueryResponse response = getSearchClient().search(request);
      FacetResponse facetResponse = response.getFacet("all_facet_date");
      
      if (facetResponse == null) return res;
      
      DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); 
      int count = 0;
      for (FacetBucket b : facetResponse) {
        if (count >= MAX_COUNT) break;
        // 
        // Date
        String strDate = b.getLabel();
        if (strDate.length() < 10) continue;
        
        // Note this format matches what we get back from attivio
        // 2006-08-30T00:00:00, just want the date
        strDate = strDate.substring(0, 10);
        Date date = null;
        long lDate = 0L;
        try {
          date = (Date)formatter.parse(strDate);
          if (date == null) continue;
          lDate = date.getTime();
          if (lDate == 0L) continue;
          // System.out.println(" Doc Date: " + Long.toString(lDate));
        } catch (ParseException e) {
          System.err.println("Error parsing date: "+ strDate);
        }
        long lValue = b.getCount();
        count++;
        Map<String, Object> map = new HashMap<String, Object>();

        //
        // fill out our results
        map.put("date", lDate);
        map.put("count", lValue);
        // System.out.println(" adding " + strDate + " with count " + Long.toString(lValue));
        res.add(map);
      }
    } catch (AttivioException e) {
      System.err.println(e.getMessage());
    }
    return res;
  }
}
