/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.ofbiz.entity.finder;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.collections.FlexibleMapAccessor;
import org.ofbiz.base.util.string.FlexibleStringExpander;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericPK;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelField;
import org.w3c.dom.Element;

/**
 * Uses the delegator to find entity values by a condition
 *
 */
@SuppressWarnings("serial")
public class PrimaryKeyFinder extends Finder {
    public static final String module = PrimaryKeyFinder.class.getName();

    protected FlexibleMapAccessor<Object> valueNameAcsr;
    protected FlexibleStringExpander autoFieldMapExdr;
    protected Map<FlexibleMapAccessor<Object>, Object> fieldMap;
    protected List<FlexibleStringExpander> selectFieldExpanderList;

    public PrimaryKeyFinder(Element entityOneElement) {
        super(entityOneElement);
        if (UtilValidate.isNotEmpty(entityOneElement.getAttribute("value-field"))) {
            this.valueNameAcsr = FlexibleMapAccessor.getInstance(entityOneElement.getAttribute("value-field"));
        } else {
            this.valueNameAcsr = FlexibleMapAccessor.getInstance(entityOneElement.getAttribute("value-name"));
        }
        this.autoFieldMapExdr = FlexibleStringExpander.getInstance(entityOneElement.getAttribute("auto-field-map"));

        // process field-map
        this.fieldMap = EntityFinderUtil.makeFieldMap(entityOneElement);

        // process select-field
        selectFieldExpanderList = EntityFinderUtil.makeSelectFieldExpanderList(entityOneElement);
    }

    @Override
    public void runFind(Map<String, Object> context, Delegator delegator) throws GeneralException {
        String entityName = this.entityNameExdr.expandString(context);

        String useCacheString = this.useCacheStrExdr.expandString(context);
        // default to false
        boolean useCacheBool = "true".equals(useCacheString);

        String autoFieldMapString = this.autoFieldMapExdr.expandString(context);
        // default to true
        boolean autoFieldMapBool = !"false".equals(autoFieldMapString);

        ModelEntity modelEntity = delegator.getModelEntity(entityName);
        if (modelEntity == null) {
            throw new IllegalArgumentException("No entity definition found for entity name [" + entityName + "]");
        }
        
        GenericValue valueOut = runFind(modelEntity, context, delegator, useCacheBool, autoFieldMapBool, this.fieldMap, this.selectFieldExpanderList);

        //Debug.logInfo("PrimaryKeyFinder: valueOut=" + valueOut, module);
        //Debug.logInfo("PrimaryKeyFinder: going into=" + this.valueNameAcsr.getOriginalName(), module);
        if (!valueNameAcsr.isEmpty()) {
           this.valueNameAcsr.put(context, valueOut);
        } else {
           if (valueOut != null) {
               context.putAll(valueOut);
           }
        }
    }

    public static GenericValue runFind(ModelEntity modelEntity, Map<String, Object> context, Delegator delegator, boolean useCache, boolean autoFieldMap,
            Map<FlexibleMapAccessor<Object>, Object> fieldMap, List<FlexibleStringExpander> selectFieldExpanderList) throws GeneralException {

        // assemble the field map
        Map<String, Object> entityContext = new HashMap<String, Object>();
        if (autoFieldMap) {
            // try a map called "parameters", try it first so values from here are overridden by values in the main context
            Object parametersObj = context.get("parameters");
            Boolean parametersObjExists = parametersObj != null && parametersObj instanceof Map<?, ?>;
            // only need PK fields
            Iterator<ModelField> iter = modelEntity.getPksIterator();
            while (iter.hasNext()) {
                ModelField curField = iter.next();
                String fieldName = curField.getName();
                Object fieldValue = null;
                if (parametersObjExists) {        
                    fieldValue = ((Map<?, ?>) parametersObj).get(fieldName);
                }
                if (context.containsKey(fieldName)) {
                    fieldValue = context.get(fieldName);
                }
                entityContext.put(fieldName, fieldValue);
            }
        }
        EntityFinderUtil.expandFieldMapToContext(fieldMap, context, entityContext);
        //Debug.logInfo("PrimaryKeyFinder: entityContext=" + entityContext, module);
        // then convert the types...
        
        // need the timeZone and locale for conversion, so add here and remove after
        entityContext.put("locale", context.get("locale"));
        entityContext.put("timeZone", context.get("timeZone"));
        modelEntity.convertFieldMapInPlace(entityContext, delegator);
        entityContext.remove("locale");
        entityContext.remove("timeZone");

        // get the list of fieldsToSelect from selectFieldExpanderList
        Set<String> fieldsToSelect = EntityFinderUtil.makeFieldsToSelect(selectFieldExpanderList, context);

        //if fieldsToSelect != null and useCacheBool is true, throw an error
        if (fieldsToSelect != null && useCache) {
            throw new IllegalArgumentException("Error in entity-one definition, cannot specify select-field elements when use-cache is set to true");
        }

        try {
            GenericValue valueOut = null;
            GenericPK entityPK = delegator.makePK(modelEntity.getEntityName(), entityContext);

            // make sure we have a full primary key, if any field is null then just log a warning and return null instead of blowing up
            if (entityPK.containsPrimaryKey(true)) {
                if (useCache) {
                    valueOut = delegator.findOne(entityPK.getEntityName(), entityPK, true);
                } else {
                    if (fieldsToSelect != null) {
                        valueOut = delegator.findByPrimaryKeyPartial(entityPK, fieldsToSelect);
                    } else {
                        valueOut = delegator.findOne(entityPK.getEntityName(), entityPK, false);
                    }
                }
            } else {
                if (Debug.infoOn()) Debug.logInfo("Returning null because found incomplete primary key in find: " + entityPK, module);
            }

            return valueOut;
        } catch (GenericEntityException e) {
            String errMsg = "Error finding entity value by primary key with entity-one: " + e.toString();
            Debug.logError(e, errMsg, module);
            throw new GeneralException(errMsg, e);
        }
    }
}
