/*-
 * ============LICENSE_START=======================================================
 * OSAM
 * ================================================================================
 * Copyright (C) 2018 AT&T
 * ================================================================================
 * Licensed 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.
 * ============LICENSE_END=========================================================
 */
package org.onap.osam.job.command;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.onap.osam.job.dao.job.JobStatus;
import org.onap.osam.job.dao.job.OsamJob;
import org.onap.osam.job.IJobFactory;
import org.onap.osam.job.NextCommand;
import org.onap.osam.job.AsyncJobService;
import org.onap.osam.job.command.WatchingCommand;
import org.onap.osam.job.impl.JobSharedData;
import org.onap.osam.job.repository.job.OsamJobRepository;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

public class WatchingCommandTest {

    @Mock
    private AsyncJobService asyncInstantiationBL;

    @Mock
    private OsamJobRepository osamJobRepository;

    @InjectMocks
    private WatchingCommand watchingCommand = new WatchingCommand();

    @DataProvider
    public static Object[][] expectedJobStatusDataProvider() {
        return new Object[][]{
                {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED), JobStatus.COMPLETED, true},
                {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS, true},
                {Arrays.asList(JobStatus.STOPPED, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS, false},
                {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.FAILED), JobStatus.IN_PROGRESS, true},
                {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.COMPLETED), JobStatus.IN_PROGRESS, true},
                {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS), JobStatus.IN_PROGRESS, true},
                {Arrays.asList(null, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS, true},
                {Arrays.asList(null, JobStatus.IN_PROGRESS), JobStatus.IN_PROGRESS, true},
                {Arrays.asList(null, JobStatus.FAILED), JobStatus.COMPLETED_WITH_ERRORS, false},
                {new ArrayList<>(), JobStatus.COMPLETED, true}
        };
    }

    @BeforeMethod
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    }

    @Test(dataProvider = "expectedJobStatusDataProvider")
    public void testAssertNextCommandIsValid(List<JobStatus> childJobs, JobStatus expectedCommandStatus, boolean isService) {
        //init sql result mock
        List<OsamJob> mockChildren = childJobs.stream().map(st -> {
            OsamJob job = new OsamJob();
            job.setUuid(UUID.randomUUID());
            job.setStatus(st);
            return job;
        }).collect(Collectors.toList());
        when(osamJobRepository.findAllByUuid(any()))
                .thenReturn(mockChildren);

        //init job data for watching command
        UUID jobUUID = UUID.randomUUID();
        JobSharedData sharedData = new JobSharedData(jobUUID, "mockedUserID", mock(TestRequest.class));
        List<UUID> uuids = mockChildren.stream().map(job -> job.getUuid()).collect(Collectors.toList());
        watchingCommand.init(sharedData, uuids, isService);

        //execute command and verify
        NextCommand nextCommand = watchingCommand.call();
        assertThat(nextCommand.getStatus(), is(expectedCommandStatus));
    }

    public static class TestRequest implements IJobFactory.AsyncJobRequest{}
}
