package it.mytria.portal.product;


import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.jahia.data.JahiaData;
import org.jahia.data.containers.JahiaContainer;
import org.jahia.data.containers.JahiaContainerList;
import org.jahia.data.fields.FieldTypes;
import org.jahia.exceptions.JahiaException;

import org.jahia.params.ParamBean;

import org.jahia.registries.ServicesRegistry;
import org.jahia.services.cache.CacheFactory;
import org.jahia.services.fields.ContentPageField;
import org.jahia.services.pages.ContentPage;
import org.jahia.services.pages.JahiaPage;
import org.jahia.services.version.EntryLoadRequest;

import it.mytria.portal.config.bo.Site;
import it.mytria.portal.erpcategory.ErpCategoryPageBuilder;
import it.mytria.portal.util.DynamicCreationUtil;




public class ProductPageBuilder {
    
    private static final String className = ProductPageBuilder.class.getName();

    private static final Log log = LogFactory.getLog(ProductPageBuilder.class);
    
                
    public static void buildProductPage( Product product, ParamBean paramBean, Site site ) throws Exception {
        
        log.debug(className + " - buildProductPage | entered with site " + site);
        
        log.info(className + " - buildProductPage | entered with product [" + product.getId() + "] branchId [" + product.getBranchId() + "]");        
        
        // 1 - we look for the page with template 'manfrotto_product_list' where we will create a new 
        // comntainer with product name, description, and with a jahia page representing the detail of the product itself
        // RULE We are able to retrieve the exact unique page thanks to the branchId of the product
        // product.branchId() = erpCategory.getUniqueIdentifier()
        JahiaPage erpCategoryProductListPage = 
                           DynamicCreationUtil.findPageByPropertyKeyAndUniqueValue( ErpCategoryPageBuilder.ERP_CATEGORY_PAGE_PROPERTY_KEY, 
                																																		product.getBranchId(), paramBean );     
        
        log.info(className + " - buildProductPage | container for product [" + product.getId() 
                           + "] will be placed in page [" + erpCategoryProductListPage.getID() + "]"); 
        
        
        // fundamental for building everything in the right place
        paramBean.changePage( ContentPage.getPage(erpCategoryProductListPage.getID(), true) );

        log.debug(className + " - buildProductPage, paramBean now points to page [" + paramBean.getPage().getTitle()
                            + "], starting to create a new jahiadata based on this parambean");

        // must create everytime a jahiadata, can't reuse the same instance
        JahiaData jahiaData = new JahiaData( paramBean );

        // now also the jahiaData has the correct page as it uses parambean's one so container / field declaration happen in the right place
        declareContainerAndField(jahiaData);

        final JahiaContainerList containerList = jahiaData.containers().getContainerList( "productContainer" );

        log.debug(className + " - buildSinglePage, containerList def name is [" + containerList.getDefinition().getName() + "]");

        final JahiaContainer productContainer = new JahiaContainer(0, // id
                                                                   paramBean.getJahiaID(), 
                                                                   paramBean.getPageID(), 
                                                                   containerList.getID(), 
                                                                   0, // rank
                                                                   containerList.getAclID(), 
                                                                   containerList.getctndefid(), // container definition id
                                                                   0, // versionId
                                                                   EntryLoadRequest.STAGING_WORKFLOW_STATE);

        // this will save this specific instance of container
        ServicesRegistry.getInstance().getJahiaContainersService().saveContainer( productContainer, 0, paramBean);
        
        // TODO manage null list, nothing to do except avoiding NullPointerException
        List localizedProductList = product.getLocalizedproductList();                
        
        Iterator localizedProductListIterator = localizedProductList.iterator();

        // create map that stores, for each language, product name and description
        Map localizedProductNameMap = new HashMap();
        Map localizedProductDescriptionMap = new HashMap();

        LocalizedProduct localizedProduct;
        String languageCode;
        while ( localizedProductListIterator.hasNext() ) {

            localizedProduct = ( LocalizedProduct ) localizedProductListIterator.next();
            languageCode = localizedProduct.getLanguage();
            localizedProductNameMap.put( languageCode, localizedProduct.getName() );
            localizedProductDescriptionMap.put( languageCode, localizedProduct.getDescription());

        }

        log.debug(className + " - buildSinglePage, localizedProductNameMap is " + localizedProductNameMap );
        log.debug(className + " - buildSinglePage, localizedProductDescriptionMap is " + localizedProductDescriptionMap );

        // TODO take from siteConfig the name of the fields / template
        // TODO pass the default language (english in manfrotto case)
        DynamicCreationUtil.createSmallTextField( paramBean, paramBean.getPage(), site, productContainer, 
                                                  "productName", localizedProductNameMap, "en");
        DynamicCreationUtil.createSmallTextField(paramBean, paramBean.getPage(), site, productContainer, 
                																 "productDescription", localizedProductDescriptionMap, "en");
        
        
        ContentPageField contentPageField = DynamicCreationUtil.createPageField( paramBean, erpCategoryProductListPage, site, 
                																																 productContainer, 
                																																 "manfrotto_product_detail", "productPage", 
                																																 localizedProductNameMap, "en");   
        
        // the part for inserting the dimension table list              
        
        ContentPage productContentPage = contentPageField.getContentPage( paramBean, true );
        
        log.debug(className + " - buildProductPage, found product detail contentPage [" + productContentPage.getID() + "]");
        
        setDimensionsForProductDetail( paramBean, productContentPage, site, "productDetailContainer", "productDimension", product);
        
        
        //
        
                                                               
        // invalidate parent page as we have just added a new container on it
        // TODO verify cache deletion
        CacheFactory.getHtmlCache().invalidatePageEntries( String.valueOf( erpCategoryProductListPage.getID() ) );        
                                       
    }
    
    
    
    
    
    // TODO retrieve these informations from site template definition for
    // product template
    private static void declareContainerAndField( JahiaData jahiaData ) throws JahiaException {

        // Have we already declared this container in this page ?
        // TODO seems necessary for avoiding 'already declared' exception when declaring n times per same page, ask jahia, repeat test
        if (jahiaData.containers().checkDeclared("productContainer")) {

            log.debug(className + " - declareContainerAndField | [productContainer] was already declared, silently returning");

        } else {
                        
            // TODO externalize these names
            jahiaData.containers().declareField("productContainer", "productPage", "productPage", FieldTypes.PAGE, "productPage");
            jahiaData.containers().declareField("productContainer", "productName", "productName", FieldTypes.SMALLTEXT, "productName");
            jahiaData.containers().declareField("productContainer", "productDescription", "productDescription", 
                                                FieldTypes.SMALLTEXT, "productDescription");

            Vector fieldsVector = new Vector();
            fieldsVector.add("productPage");
            fieldsVector.add("productName");
            fieldsVector.add("productDescription");

            jahiaData.containers().declareContainer( "productContainer", "container for product", fieldsVector );

            log.debug( className + ".declareContainerAndField | Container [productContainer] was correctly defined with its fields" );

        }

    }
    
    
    private static void setDimensionsForProductDetail ( ParamBean paramBean, ContentPage productDetailContentPage, Site site,
             																						String containerName, String fieldName, Product product) throws Exception{
        
        
        ContentPage originalParamBeanPage = paramBean.getContentPage();
        
        // force parambean to work with productDetail page 
        paramBean.changePage( productDetailContentPage );
        
        // need a jahiaData for declaring product detail container and its unique big text field
        JahiaData jahiaData = new JahiaData( paramBean );
     
        if (jahiaData.containers().checkDeclared( containerName )) {

            log.debug(className + " - setDimensionsForProductDetail | [" + containerName + "] was already declared, silently returning");

        } else {
                        
            // TODO externalize these names
      		  jahiaData.containers().declareField( containerName, fieldName, fieldName, FieldTypes.BIGTEXT, "");

      		  Vector productDetailFields = new Vector( );
            productDetailFields.add( fieldName );
      		  jahiaData.containers().declareContainer( containerName, containerName, productDetailFields );
        }
        
        
        final JahiaContainerList containerList = jahiaData.containers().getContainerList( containerName );

        log.debug(className + " - setDimensionsForProductDetail, containerList def name is [" + containerList.getDefinition().getName() + "]");

        final JahiaContainer productContainer = new JahiaContainer(0, // id
                                                                   paramBean.getJahiaID(), 
                                                                   paramBean.getPageID(), 
                                                                   containerList.getID(), 
                                                                   0, // rank
                                                                   containerList.getAclID(), 
                                                                   containerList.getctndefid(), // container definition id
                                                                   0, // versionId
                                                                   EntryLoadRequest.STAGING_WORKFLOW_STATE);
        
        // this will save this specific instance of container
        ServicesRegistry.getInstance().getJahiaContainersService().saveContainer( productContainer, 0, paramBean );        
        
        // the map that will store, per each language, the html view on product dimensions
        Map localizedproductDimensionMap = new HashMap();
        
        List localizedProductList = product.getLocalizedproductList();
        Iterator localizedProductListIterator = localizedProductList.iterator();                 
        LocalizedProduct localizedProduct;
        String languageCode;
                
        while ( localizedProductListIterator.hasNext() ) {

            localizedProduct = ( LocalizedProduct ) localizedProductListIterator.next();
            languageCode = localizedProduct.getLanguage();
            // TODO temporary html view.....
            localizedproductDimensionMap.put( languageCode, localizedProduct.dimensionList.toString() );

        }        
        
        // TODO URGENTLY !!!!!!!
        // VISTA HTML DU LISTA DI DIMENSIONI !!!!!!!!!!!!
        
        
        log.debug(className + " - setDimensionsForProductDetail, dimension html view is [" + localizedproductDimensionMap + "]");
        
        DynamicCreationUtil.createBigTextField( paramBean, productDetailContentPage.getPage( paramBean ), site,
                																productContainer, fieldName, localizedproductDimensionMap, "en");
        
        paramBean.changePage( originalParamBeanPage );
        
       
    }   
    
    
              
}