/*
 * ProActive Parallel Suite(TM):
 * The Open Source library for parallel and distributed
 * Workflows & Scheduling, Orchestration, Cloud Automation
 * and Big Data Analysis on Enterprise Grids & Clouds.
 *
 * Copyright (c) 2007 - 2017 ActiveEon
 * Contact: contact@activeeon.com
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation: version 3 of
 * the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * If needed, contact us to obtain a release under GPL Version 2 or 3
 * or a different license than the AGPL.
 */
package org.ow2.proactive.scheduling.api.graphql.fetchers;

import java.util.Comparator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.ow2.proactive.scheduler.core.db.JobData;
import org.ow2.proactive.scheduling.api.graphql.fetchers.converter.JobInputConverter;
import org.ow2.proactive.scheduling.api.graphql.fetchers.converter.JobTaskFilterInputBiFunction;
import org.ow2.proactive.scheduling.api.graphql.fetchers.cursor.JobCursorMapper;
import org.ow2.proactive.scheduling.api.graphql.schema.type.DataManagement;
import org.ow2.proactive.scheduling.api.graphql.schema.type.Job;

import com.google.common.base.CaseFormat;

import graphql.schema.DataFetchingEnvironment;


/**
 * @author ActiveEon Team
 */
public class JobDataFetcher extends DatabaseConnectionFetcher<JobData, Job> {

    public JobDataFetcher(Supplier<EntityManager> entityManager) {
        super(entityManager);
    }

    @Override
    public Object get(DataFetchingEnvironment environment) {

        Function<Root<JobData>, Path<? extends Number>> entityId = root -> root.get("id");

        BiFunction<CriteriaBuilder, Root<JobData>, List<Predicate[]>> criteria = new JobTaskFilterInputBiFunction(new JobInputConverter(),
                                                                                                                  environment);

        return createPaginatedConnection(environment,
                                         JobData.class,
                                         entityId,
                                         Comparator.comparingLong(JobData::getId),
                                         criteria,
                                         new JobCursorMapper());
    }

    @Override
    protected Stream<Job> dataMapping(Stream<JobData> dataStream) {
        return dataStream.parallel()
                         .map(jobData -> Job.builder()
                                            .dataManagement(DataManagement.builder()
                                                                          .globalSpaceUrl(jobData.getGlobalSpace())
                                                                          .inputSpaceUrl(jobData.getInputSpace())
                                                                          .outputSpaceUrl(jobData.getOutputSpace())
                                                                          .userSpaceUrl(jobData.getUserSpace())
                                                                          .build())
                                            .description(jobData.getDescription())
                                            .finishedTime(jobData.getFinishedTime())
                                            .genericInformation(jobData.getGenericInformation())
                                            .id(jobData.getId())
                                            .inErrorTime(jobData.getInErrorTime())
                                            .lastUpdatedTime(jobData.getLastUpdatedTime())
                                            .maxNumberOfExecution(jobData.getMaxNumberOfExecution())
                                            .name(jobData.getJobName())
                                            .numberOfFailedTasks(jobData.getNumberOfFailedTasks())
                                            .numberOfFaultyTasks(jobData.getNumberOfFaultyTasks())
                                            .numberOfFinishedTasks(jobData.getNumberOfFinishedTasks())
                                            .numberOfInErrorTasks(jobData.getNumberOfInErrorTasks())
                                            .numberOfPendingTasks(jobData.getNumberOfPendingTasks())
                                            .numberOfRunningTasks(jobData.getNumberOfRunningTasks())
                                            .onTaskError(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
                                                                                   jobData.getOnTaskErrorString()))
                                            .owner(jobData.getOwner())
                                            .priority(jobData.getPriority().name())
                                            .projectName(jobData.getProjectName())
                                            .removedTime(jobData.getRemovedTime())
                                            .status(jobData.getStatus().name())
                                            .startTime(jobData.getStartTime())
                                            .submittedTime(jobData.getSubmittedTime())
                                            .totalNumberOfTasks(jobData.getTotalNumberOfTasks())
                                            .variables(jobData.getVariables() == null ? null
                                                                                      : jobData.getVariables()
                                                                                               .entrySet()
                                                                                               .stream()
                                                                                               .collect(Collectors.toMap(e -> e.getKey(),
                                                                                                                         e -> e.getValue()
                                                                                                                               .getValue())))
                                            .build());
    }

}

@@ -2023,16 +2023,63 @@
 eFormat;
+%0Aimport com.google.common.collect.ImmutableMap;
 %0A%0Aimport
@@ -6107,32 +6107,188 @@
 umberOfTasks())%0A
+                                            // TODO Currently map the JobVariable object to a simple string (its value). Need to map the whole object later%0A
                 
@@ -6359,20 +6359,33 @@
  null ? 
-null
+ImmutableMap.of()
 %0A       

add comments as requested by Laurent