/**
* Service class that encapsulates the business logic for Task searches.
*/
class TaskSearchService {

    boolean transactional = false

    def authService
    def dateUtilService
    def messageSource

    def paramsMax = 100000

    /**
    * Selects and returns the correct search results based on the supplied quickSearch.
    * @param params The request params, may contain params.quickSearch string to specify the search.
    * @param locale The locale to use when generating result.message.
    */
    def getQuickSearch(params, locale) {
        def result = [:]
        def currentUser = authService.currentUser
        result.quickSearch = params.quickSearch ?: "searchPlannersRange"

        def getMessage = { Map m ->
            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
        }

        switch (result.quickSearch) {
            case "myTodays":
                result.taskInstanceList = getMyTodays(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.my.todays", args:[currentUser])
                else
                    result.message = getMessage(code:"task.search.text.my.todays.none.found", args:[currentUser])
                break
            case "myYesterdays":
                result.taskInstanceList = getMyTodays(params, -1)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.my.yesterdays", args:[currentUser])
                else
                    result.message = getMessage(code:"task.search.text.my.yesterdays.none.found", args:[currentUser])
                break
            case "myTomorrows":
                result.taskInstanceList = getMyTodays(params, 1)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.my.tomorrows", args:[currentUser])
                else
                    result.message = getMessage(code:"task.search.text.my.tomorrows.none.found", args:[currentUser])
                break
            case "myPastWeek":
                result.taskInstanceList = getMyPastWeek(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.my.past.week", args:[currentUser])
                else
                    result.message = getMessage(code:"task.search.text.my.past.week.none.found", args:[currentUser])
                break
            case "todays":
                result.taskInstanceList = getTodays(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.todays")
                else
                    result.message = getMessage(code:"task.search.text.todays.none.found")
                break
            case "yesterdays":
                result.taskInstanceList = getTodays(params, -1)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.yesterdays")
                else
                    result.message = getMessage(code:"task.search.text.yesterdays.none.found")
                break
            case "tomorrows":
                result.taskInstanceList = getTodays(params, 1)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.tomorrows")
                else
                    result.message = getMessage(code:"task.search.text.tomorrows.none.found")
                break
            case "pastWeek":
                result.taskInstanceList = getPastWeek(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.past.week")
                else
                    result.message = getMessage(code:"task.search.text.past.week.none.found")
                break
            case "budgetUnplanned":
                result.taskInstanceList = getBudgetUnplanned(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.budget.unplanned")
                else
                    result.message = getMessage(code:"task.search.text.budget.unplanned.none.found")
                break
            case "budgetPlanned":
                result.taskInstanceList = getBudgetPlanned(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.budget.planned")
                else
                    result.message = getMessage(code:"task.search.text.budget.planned.none.found")
                break
            default:
                result.taskInstanceList = getPlannersRange(params)
                if(result.taskInstanceList.totalCount > 0)
                    result.message = getMessage(code:"task.search.text.planners.range")
                else
                    result.message = getMessage(code:"task.search.text.planners.range.none.found")
                break
        } // switch.

        // Success.
        return result

    } // getQuickSearch

    def getTodays(params, dayAdjustment=0) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "attentionFlag"
        params.order = params?.order ?: "desc"

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort, 
            order: params.order) {
                ge("targetStartDate", dateUtilService.today+dayAdjustment)
                lt("targetStartDate", dateUtilService.tomorrow+dayAdjustment)
                eq("trash", false)
            }
    }

    def getMyTodays(params, dayAdjustment=0) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "attentionFlag"
        params.order = params?.order ?: "desc"

        def currentUser = authService.currentUser

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort, 
            order: params.order) {
                ge("targetStartDate", dateUtilService.today+dayAdjustment)
                lt("targetStartDate", dateUtilService.tomorrow+dayAdjustment)
                eq("trash", false)
                eq("approved", true)
                or {
                    eq("leadPerson", currentUser)
                    assignedPersons {
                        eq("person", currentUser)
                    }
                    assignedGroups {
                        currentUser.personGroups.each() {
                            eq("personGroup", it)
                        }
                    } // assignedGroups
                } // or
            } // criteria
    } // getMyTodays

    def getPastWeek(params) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "attentionFlag"
        params.order = params?.order ?: "desc"

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort, 
            order: params.order) {
                ge("targetStartDate", dateUtilService.oneWeekAgo)
                lt("targetStartDate", dateUtilService.tomorrow)
                eq("trash", false)
            }
    }

    def getMyPastWeek(params) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "attentionFlag"
        params.order = params?.order ?: "desc"

        def currentUser = authService.currentUser

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort, 
            order: params.order) {
                ge("targetStartDate", dateUtilService.oneWeekAgo)
                lt("targetStartDate", dateUtilService.tomorrow)
                eq("trash", false)
                eq("approved", true)
                or {
                    eq("leadPerson", currentUser)
                    assignedPersons {
                        eq("person", currentUser)
                    }
                    assignedGroups {
                        currentUser.personGroups.each() {
                            eq("personGroup", it)
                        }
                    } // assignedGroups
                } // or
            } // criteria
    } // getMyPastWeek

    def getBudgetPlanned(params) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "targetStartDate"
        params.order = params?.order ?: "asc"

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort,
            order: params.order) {
                eq("taskBudgetStatus", TaskBudgetStatus.read(2))
                ge("targetStartDate", dateUtilService.oneWeekAgo)
                lt("targetStartDate", dateUtilService.tomorrow)
                eq("trash", false)
            }
    }

    def getBudgetUnplanned(params) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "targetStartDate"
        params.order = params?.order ?: "asc"

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort,
            order: params.order) {
                eq("taskBudgetStatus", TaskBudgetStatus.read(1))
                ge("targetStartDate", dateUtilService.oneWeekAgo)
                lt("targetStartDate", dateUtilService.tomorrow)
                eq("trash", false)
            }
    }

    def getPlannersRange(params) {
        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
        params.offset = params?.offset?.toInteger() ?: 0
        params.sort = params?.sort ?: "targetStartDate"
        params.order = params?.order ?: "asc"

        def taskInstanceList = Task.createCriteria().list(
            max: params.max,
            offset: params.offset,
            sort: params.sort,
            order: params.order) {
                ge("targetStartDate", dateUtilService.oneWeekAgo)
                lt("targetStartDate", dateUtilService.today + 15)
                eq("trash", false)
            }
    }
}
