/*
 * 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.
 */

import org.apache.ofbiz.base.util.StringUtil
import org.apache.ofbiz.base.util.UtilDateTime
import org.apache.ofbiz.base.util.Debug
import org.apache.ofbiz.entity.util.EntityFindOptions
import org.apache.ofbiz.entity.condition.EntityCondition
import org.apache.ofbiz.entity.condition.EntityConditionList
import org.apache.ofbiz.entity.condition.EntityExpr
import org.apache.ofbiz.entity.condition.EntityFieldValue
import org.apache.ofbiz.entity.condition.EntityFunction
import org.apache.ofbiz.entity.condition.EntityOperator
import org.apache.ofbiz.entity.util.EntityUtilProperties

def mainAndConds = []
def orExprs = []
def entityName = context.entityName
def searchFields = context.searchFields
def displayFields = context.displayFields ?: searchFields
def searchDistinct = Boolean.valueOf(context.searchDistinct ?: false)

def searchValueFieldName = parameters.term
def fieldValue = null
if (searchValueFieldName) {
    fieldValue = searchValueFieldName
} else if (parameters.searchValueFieldName) { // This is to find the description of a lookup value on initialization.
    fieldValue = parameters.get(parameters.searchValueFieldName)
    context.description = "true"
}

def searchType = context.searchType
def displayFieldsSet = null

def conditionDates = context.conditionDates
def fromDateName = null
def thruDateName = null
def filterByDateValue = null

//If conditionDates is present on context, resolve values use add condition date to the condition search
if (conditionDates) {
    filterByDateValue = conditionDates.filterByDateValue ?: UtilDateTime.nowTimestamp()
    fromDateName = conditionDates.fromDateName ?: null
    thruDateName = conditionDates.thruDateName ?: null
    //if the field filterByDate is present, init default value for fromDate and thruDate
    if (!fromDateName && !thruDateName) {
        fromDateName = "fromDate"
        thruDateName = "thruDate"
    }
}

if (searchFields && fieldValue) {
    def searchFieldsList = StringUtil.toList(searchFields)
    displayFieldsSet = StringUtil.toSet(displayFields)
    if (context.description && fieldValue instanceof java.lang.String) {
        returnField = parameters.searchValueFieldName
    } else {
        returnField = searchFieldsList[0] //default to first element of searchFields
        displayFieldsSet.add(returnField) //add it to select fields, in case it is missing
    }
    context.returnField = returnField
    context.displayFieldsSet = displayFieldsSet
    if ("STARTS_WITH".equals(searchType)) {
        searchValue = fieldValue.toUpperCase() + "%"
    } else if ("EQUALS".equals(searchType)) {
        searchValue = fieldValue
    } else {//default is CONTAINS
        searchValue = "%" + fieldValue.toUpperCase() + "%"
    }
    searchFieldsList.each { fieldName ->
        if ("EQUALS".equals(searchType)) {
            orExprs.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(searchFieldsList[0]), EntityOperator.EQUALS, searchValue))
            return //in case of EQUALS, we search only a match for the returned field
        } else {
            orExprs.add(EntityCondition.makeCondition(EntityFunction.UPPER(EntityFieldValue.makeFieldValue(fieldName)), EntityOperator.LIKE, searchValue))
        }        
    }
}

/* the following is part of an attempt to handle additional parameters that are passed in from other form fields at run-time,
 * but that is not supported by the Jquery Autocompleter, but this is still useful to pass parameters from the
 * lookup screen definition:
 */
def conditionFields = context.conditionFields
if (conditionFields) {
    // these fields are for additonal conditions, this is a Map of name/value pairs
    for (conditionFieldEntry in conditionFields.entrySet()) {
        if (conditionFieldEntry.getValue() instanceof java.util.List) {
            def orCondFields = []
            for (entry in conditionFieldEntry.getValue()) {
                orCondFields.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(conditionFieldEntry.getKey()), EntityOperator.EQUALS, entry))
            }
            mainAndConds.add(EntityCondition.makeCondition(orCondFields, EntityOperator.OR))
        } else {
            mainAndConds.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(conditionFieldEntry.getKey()), EntityOperator.EQUALS, conditionFieldEntry.getValue()))
        }
    }
}

if (orExprs && entityName && displayFieldsSet) {
    mainAndConds.add(EntityCondition.makeCondition(orExprs, EntityOperator.OR))

    //if there is an extra condition, add it to main condition list
    if (context.andCondition && context.andCondition instanceof EntityCondition) {
        mainAndConds.add(context.andCondition)
    }
    if (conditionDates) {
        def condsDateList = []
        if (thruDateName) {
            def condsByThruDate = []
            condsByThruDate.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(thruDateName), EntityOperator.GREATER_THAN, filterByDateValue))
            condsByThruDate.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(thruDateName), EntityOperator.EQUALS, null))
            condsDateList.add(EntityCondition.makeCondition(condsByThruDate, EntityOperator.OR))
        }

        if (fromDateName) {
            def condsByFromDate = []
            condsByFromDate.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(fromDateName), EntityOperator.LESS_THAN_EQUAL_TO, filterByDateValue))
            condsByFromDate.add(EntityCondition.makeCondition(EntityFieldValue.makeFieldValue(fromDateName), EntityOperator.EQUALS, null))
            condsDateList.add(EntityCondition.makeCondition(condsByFromDate, EntityOperator.OR))
        }

        mainAndConds.add(EntityCondition.makeCondition(condsDateList, EntityOperator.AND))
    }

    def entityConditionList = EntityCondition.makeCondition(mainAndConds, EntityOperator.AND)

    String viewSizeStr = context.autocompleterViewSize
    Integer autocompleterViewSize = Integer.valueOf(viewSizeStr ?: 10)
    EntityFindOptions findOptions = new EntityFindOptions()
    findOptions.setMaxRows(autocompleterViewSize)
    findOptions.setDistinct(searchDistinct)

    autocompleteOptions = delegator.findList(entityName, entityConditionList, displayFieldsSet, StringUtil.toList(displayFields), findOptions, false)
    if (autocompleteOptions) {
        context.autocompleteOptions = autocompleteOptions
    }
}
