package com.k_int.discover.lookup.collection;

import com.k_int.aggregator.datamodel.AggregatorCollectionHDO;
import com.k_int.aggregator.datamodel.AggregatorCollectionTypeHDO;
import com.k_int.aggregator.datamodel.AggregatorResourceHDO;
import com.k_int.discover.datamodel.CultureGrid_AutomaticCollLinkHDO;
import com.k_int.discover.datamodel.CultureGrid_BaseHDO;
import com.k_int.discover.datamodel.CultureGrid_CollectionHDO;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * An action that looks up and returns the complete collection hierarchy for use
 *
 * @author rpb rich@k-int.com
 * @version 1.0 31.08.10
 * 
 */
public class LookupHierarchy extends ActionSupport implements ServletRequestAware, ApplicationContextAware {
	private static final long serialVersionUID = -7836392394036972534L;

	private static Log log = LogFactory.getLog(LookupHierarchy.class);
    
    protected HttpServletRequest request;
    protected ApplicationContext ctx;
    protected SessionFactory factory;

    public void setServletRequest(HttpServletRequest request) { this.request = request; }
    public void setApplicationContext(ApplicationContext ctx) {	this.ctx = ctx; }
    public void setSessionFactory(SessionFactory factory) { this.factory = factory; }

    private String hierarchyInfo = "";

    public String getHierarchyInfo() {
        return this.hierarchyInfo;
    }
    
    @Override
    public String execute() {
        log.debug("LookupHierarchy::execute method called");
        
        String returnValue = SUCCESS;

        Session sess = null;

        try {
            sess = factory.openSession();

            // Go and get all of the TOP_LEVEL collections
            AggregatorCollectionTypeHDO topLevelType = AggregatorCollectionTypeHDO.lookup(sess, "TOP_LEVEL");
            
            if ( topLevelType == null ) {
                // No top level type!!!
                
                // TODO
            } else {
                List<AggregatorCollectionHDO> topLevelColls = AggregatorCollectionHDO.lookupByType(sess, topLevelType);
                
                if ( topLevelColls == null || topLevelColls.isEmpty() ) {
                    // No top level colls!
                    
                    // TODO
                } else {
                    
                    StringBuilder retValBuilder =  new StringBuilder();
                    retValBuilder.append("{\"hierarchies\":[");
                    
                    // Loop through the colls and workout their hierarchy..
                    boolean previousCollOutput = false;
                    
                    for(AggregatorCollectionHDO thisTopColl: topLevelColls) {
                        
                        if ( thisTopColl.getManagementInfo().getDeletedDate() != null ) {
                            // A deleted collection - ignore it
                        } else {
                            // A live collection
                            if ( previousCollOutput ) {
                                // We've already output a collection - so continue the array
                                retValBuilder.append(",");
                            }
                            
                            String collData = processCollection(sess, thisTopColl);
                            if ( collData != null && !"".equals(collData.trim()) ) {
                                retValBuilder.append(collData);
                                previousCollOutput = true;
                            }
                        }
                        
                    }
                    
                    retValBuilder.append("]}");

                    this.hierarchyInfo = retValBuilder.toString();
                    
                    // TODO
                }
    
                        
            }
            
            
            request.setAttribute("hierarchyInfo", this.hierarchyInfo);

            
        } catch (HibernateException he) {
            log.error("HibernateException thrown: " + he.getMessage());
            he.printStackTrace();
        } finally {
            if ( sess != null ) {
                try {
                    sess.close();
                } catch (HibernateException he) {
                    // Can't do anything!
                }
            }
        }
        
        return returnValue;
    }
    
    
    private String processCollection(Session sess, AggregatorCollectionHDO collection) {
        StringBuilder returnBuilder = new StringBuilder();

        if ( collection != null && collection.getManagementInfo().getDeletedDate() == null ) {
            returnBuilder.append("{\"id\":").append(collection.getId()).append(",");
            returnBuilder.append("\"collCode\":\"").append(collection.getCollectionCode()).append("\",");
            returnBuilder.append("\"name\":\"").append(collection.getName()).append("\",");
            returnBuilder.append("\"description\":\"");
            if ( collection.getDescription() != null ) 
                returnBuilder.append(collection.getDescription());
            returnBuilder.append("\",");
            
            String childData = processChildCollections(sess, collection.getChildrenCollections());
            String linkedResData = processLinkedResData(sess, collection.getLinkedResource());
            
            returnBuilder.append("\"children\":").append(childData).append(",");
            returnBuilder.append("\"linkedResource\":").append(linkedResData);
            returnBuilder.append("}");
        } else {
            // Null or deleted collection - nothing to output..
        }
        
        return returnBuilder.toString();
        
    }
    
    private String processChildCollections(Session sess, List<AggregatorCollectionHDO> children) {
        StringBuilder childrenBuilder = new StringBuilder();
        
        if ( children != null && !children.isEmpty() ) {
            // We have children to potentially output..
        
            boolean childAdded = false;
            
            for(AggregatorCollectionHDO child: children) {
                
                if ( child.getManagementInfo().getDeletedDate() == null ) {
                    // A collection to output
                    if ( childrenBuilder.length() == 0 ) {
                        childrenBuilder.append("[");
                    } else {
                        childrenBuilder.append(",");
                    }
                    
                    childrenBuilder.append(processCollection(sess, child));
                    childAdded = true;
                    
                    
                } else {
                    // A deleted collection - ignore it
                }
                
            }
            
            if ( !childAdded ) {
                childrenBuilder.append("[");
            }
            
            childrenBuilder.append("]");
            
        } else {
            childrenBuilder.append("[]");
        }
        
        
        
        return childrenBuilder.toString();
    }


    private String processLinkedResData(Session sess, AggregatorResourceHDO resource) {
        
        StringBuilder linkedResBuilder = new StringBuilder();
        linkedResBuilder.append("{");
        
        if ( resource != null ) {
            // There is a linked resource - process it..
                                    
            // Get the datamodel object that is linked to..
            CultureGrid_BaseHDO linkedResBase = CultureGrid_BaseHDO.lookupByResourceId(sess, resource.getId());

            if ( linkedResBase != null  && linkedResBase instanceof CultureGrid_CollectionHDO ) {

                CultureGrid_CollectionHDO linkedResColl = (CultureGrid_CollectionHDO)linkedResBase;

                linkedResBuilder.append("\"resourceId\":\"").append(resource.getId()).append("\",");
                linkedResBuilder.append("\"title\":\"").append(linkedResColl.getTitle()).append("\",");
                linkedResBuilder.append("\"associatedColls\":[");
                    if ( linkedResColl.getAutoData() != null && linkedResColl.getAutoData().getAssociatedColls() != null && !linkedResColl.getAutoData().getAssociatedColls().isEmpty()) {
                        // We have something to add in..
                        boolean assocOutput = false;
                        for(CultureGrid_AutomaticCollLinkHDO anAssoc: linkedResColl.getAutoData().getAssociatedColls()) {
                            if ( assocOutput )
                                linkedResBuilder.append(",");

                            linkedResBuilder.append("{");
                            linkedResBuilder.append("\"id\":\"").append(anAssoc.getCollId()).append("\",");
                            linkedResBuilder.append("\"title\":\"").append(anAssoc.getCollTitle()).append("\",");
                            linkedResBuilder.append("\"code\":\"").append(anAssoc.getCollCode()).append("\"");
                            linkedResBuilder.append("}");
                            assocOutput = true;
                        }
                    }
                linkedResBuilder.append("]");

            } else {
                log.error("No linked resource collection found even though a resource was apparently linked!");
            }

        }
        
        linkedResBuilder.append("}");
        
        return linkedResBuilder.toString();
    }
}
