/*
 * $Id: RequestUtils.java 394468 2006-04-16 12:16:03Z tmjee $
 *
 * Copyright 2006 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.k_int.aggregator.dpp.actions;

import com.k_int.aggregator.config.DPP_Properties;
import com.k_int.aggregator.datamodel.AggregatorCollectionHDO;
import com.k_int.aggregator.datamodel.AggregatorResourceHDO;
import com.k_int.aggregator.datamodel.AggregatorSourceHDO;
import com.k_int.aggregator.datamodel.ResourceInstanceHDO;
import com.k_int.aggregator.dpp.util.AttachmentUtils;
import com.k_int.aggregator.dpp.util.AuthUtil;
import com.k_int.aggregator.dpp.util.PermissionUtils;
import com.k_int.discover.datamodel.AttachedResourceHDO;
import com.k_int.discover.datamodel.dto.AttachedResourceDTO;
import com.k_int.svc.identity.service.IdentityService;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.k_int.aggregator.util.SOLRHelper;

import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class ResourceAction extends ActionSupport implements ServletRequestAware, ApplicationContextAware {
  private static final long serialVersionUID = 1L;
  private static Log log = LogFactory.getLog(ResourceAction.class);
  private static long delete_count = 0;
  private HttpServletRequest request;
  private SessionFactory factory;
  private String resource_id;
  private AggregatorResourceHDO resource = null;
  private List<ResourceInstanceHDO> instances = null;
  private Boolean has_upload_privs = false;
  private Boolean has_edit_privs = false;
  private Boolean global_admin = false;
  private ApplicationContext ctx;
  private SimpleDateFormat formatter;
  private String action = null;
  private SOLRHelper solr_helper = null;

  public void setServletRequest(HttpServletRequest request) { this.request = request;         }
  public void setSessionFactory(SessionFactory factory)     { this.factory = factory;         }
  public void setResourceId(String resource_id)             { this.resource_id = resource_id; }
  public String getResourceId()                             { return resource_id;             }
  public void setApplicationContext(ApplicationContext ctx) { this.ctx = ctx;                 }
  public void setAction(String action) { this.action = action; }
  public void setSolrHelper(SOLRHelper solr_helper)            { this.solr_helper = solr_helper; }


  public AggregatorResourceHDO getResource()      { return resource;         }
  public List<ResourceInstanceHDO> getInstances() { return instances;        }
  public Boolean getHasUploadPrivs()              { return has_upload_privs; }
  public Boolean getHasEditPrivs()				  { return has_edit_privs; }
  public Boolean getIsGlobalAdmin()				  { return global_admin; }
  public String getFormattedCreationDate()        { return formatter.format(resource.getCreationDate());     }
  public String getFormattedModifiedDate()        { return formatter.format(resource.getLastModifiedDate()); }
  public String getFormattedDeletedDate()         { return formatter.format(resource.getDeletedDate());      }
  public String getAction()                       { return action; }

  
  public String execute() throws Exception {
    log.debug("execute");
    String result = "success";
    Session sess  = null;
    
    HttpSession http_session = request.getSession(false);
    formatter = new SimpleDateFormat("dd-MM-yyyy");

    String accept_header = request.getHeader("Accept");

    if (accept_header==null || !accept_header.contains("html")) {
      result = "success_xml";
    }

    /**
     * This is a kludge to get around the fact that IE does not send text/html, text/xhtml-xml 
     * or any of the other valid html mime types. 
     * Detect if we're dealing with IE and use html response type.
     */
    String user_agent = request.getHeader("User-Agent");
    log.debug("Received user agent header of: "+user_agent);
    if (user_agent!=null && user_agent.contains("MSIE")) {
      result = "success";
    }
    
    try {
      sess = factory.openSession();
      if (resource_id != null && resource_id.length()>0) {
        log.debug("Looking up resuource with ID "+resource_id);
        long id  = Long.parseLong(resource_id);
        resource = AggregatorResourceHDO.lookupById(sess, id);
        log.debug("Result of lookup:"+resource);

        if (resource!=null) {
          log.debug("Building instance list");
          instances = new ArrayList<ResourceInstanceHDO>();
          Query q   = sess.createQuery("from ResourceInstanceHDO where resource.id=?");
          q.setParameter(0, resource.getId());

          for (Object o : q.list()) {
            instances.add((ResourceInstanceHDO)o);
          }
          
          IdentityService ident_service = (IdentityService) ctx.getBean("IdentityService");
          Principal principal = request.getUserPrincipal();
          if (principal != null) {
        	  
            Map<String, AggregatorSourceHDO> valid_providers = AuthUtil.getValidSourcesForDepositor(ident_service,principal.getName(),sess);
            if (valid_providers.keySet().contains(resource.getSource().getIdentifier())) {
            	log.debug("setting deposit privs 1");
              has_upload_privs=true;
            } 
            
            
            Map<Long,AggregatorCollectionHDO> valid_colls = PermissionUtils.getValidCollectionsForEditor(sess, ident_service, principal.getName());
            if ( resource.getCollections() != null ) {
            	Set<AggregatorCollectionHDO> colls = resource.getCollections();
            	Iterator<AggregatorCollectionHDO> collIter = colls.iterator();
            	while(collIter.hasNext()) {
            		AggregatorCollectionHDO nextColl = collIter.next();
            		if ( nextColl != null ) {
            			if ( valid_colls.keySet().contains(nextColl.getId()) ) {
            				log.debug("setting edit privs 1");
            				has_edit_privs = true;
            				break;
            			}
            		}
            	}
            }
            
            // Ensure that admin users have the different types of permissions they need even though
            // they aren't given explicitly
            if ( request.isUserInRole("GLOBAL.admin") ) {
            	global_admin = true;
            	has_edit_privs = true;
            	has_upload_privs = true;
            } else if ( request.isUserInRole("SYSTEM.admin") ) {
            	has_edit_privs = true;
            	has_upload_privs = true;
            }
            
          }
          
          // Go and get the list of objects attached to this resource (if any) and prepare them for output
          List<AttachedResourceHDO> attachedResources = AttachmentUtils.getAttachedResources(sess, id);
          Map<String,ArrayList<AttachedResourceDTO>> tempAttachmentMap = null;
          if ( attachedResources != null ) {
        	  tempAttachmentMap = new TreeMap<String,ArrayList<AttachedResourceDTO>>();
        	  Iterator<AttachedResourceHDO> attachedResIter = attachedResources.iterator();
        	  while(attachedResIter.hasNext()) {
        		  AttachedResourceHDO nextRes = attachedResIter.next();
        		  AttachedResourceDTO resDTO = new AttachedResourceDTO(nextRes);
        		  String filename = resDTO.getFilename();
        		  ArrayList<AttachedResourceDTO> tempList = null;
        		  if ( tempAttachmentMap.containsKey(filename) ) {
        			  tempList = tempAttachmentMap.get(filename);
        		  } else {
        			  tempList = new ArrayList<AttachedResourceDTO>();
        		  }
        		  tempList.add(resDTO);
        		  
        		  tempAttachmentMap.put(filename, tempList);
        	  }
        	  
          }

          String repositoryURL = DPP_Properties.getRepositoryURL();
          request.setAttribute("repositoryURL", repositoryURL);
          request.setAttribute("attachmentMap", tempAttachmentMap);

          if ( ( action != null ) && ( has_upload_privs ) ) {
            log.debug("Processing resource action "+action);
            if ( ( action.equals("ClearChecksum") ) || ( action.equals("DeleteSolrRecord") ) ) {
              log.debug("Clearing instance checksums");
              Transaction tx = sess.beginTransaction();
              Query dq   = sess.createQuery("update ResourceInstanceHDO set checkSum=null where resource.id=?");
              dq.setParameter(0, resource.getId());
              dq.executeUpdate();
              tx.commit();
              addActionMessage("Instance checksums cleared");
            } 
            
            if ( action.equals("DeleteSolrRecord") ) {

            	log.debug("Delete SOLR Record for resource");

//            	String resource_id = ""+resource.getId();
//            	String resource_identifier = resource.getIdentifier();
//            	long create_date = resource.getCreationDate() != null ? resource.getCreationDate().getTime() : 0;
//            	String data_source_name = resource.getSource().getIdentifier();
            	log.debug("Delete SOLR Record for resource - "+(++delete_count));
            	
            	// Mark the resource as deleted in the datamodel
            	Transaction tx = sess.beginTransaction();
            	Query dq  = sess.createQuery("update AggregatorResourceHDO set deletedDate=?, deletedBy=? where id=?");
            	dq.setParameter(0, new java.sql.Timestamp(System.currentTimeMillis()));
            	dq.setParameter(1, principal.getName());
            	dq.setParameter(2, resource.getId());
            	dq.executeUpdate();
            	tx.commit();
            	
            	// Now perform the actual solr deletion
            	solr_helper.deleteById(resource.getId().toString(),false); 
            	addActionMessage("SOLR Record Deleted "+(--delete_count));
            	if ( http_session != null ) {
            		Long session_delete_count = (Long) http_session.getAttribute("DeleteCount");
            		if ( session_delete_count == null )
            			session_delete_count = new Long(0);
            		http_session.setAttribute("DeleteCount",new Long((session_delete_count.longValue())+1));
            	}
            }


            sess.evict(resource);

            // Refreshing the resource to fetch any changes.
            resource = AggregatorResourceHDO.lookupById(sess, id);
          }
          else {
            if ( action != null ) {
              addActionError("You have attempted an administrative operation without permission");
            }
          }
        }
      }
      sess.clear();
    } catch (HibernateException he ) {
      log.error("Problem with provider home",he);
    } finally {
      if (sess !=null && sess.isOpen() ) try { sess.close(); } catch (Exception e) {  }
    }

    if ( result.equalsIgnoreCase("success_xml") ) {
    	log.debug("XML response - assuming this action is a restful call. Closing session now");
        http_session.setAttribute("CloseMethod","Assumed WS Call");
        http_session.invalidate();
    }

    return result;
  }
  
  

}
