/*-
 * ============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 com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.onap.osam.job.dao.job.JobStatus;
import org.onap.osam.job.IJobFactory;
import org.onap.osam.job.IJobCommand;
import org.onap.osam.job.IJobsDataAccessService;
import org.onap.osam.job.NextCommand;
import org.onap.osam.job.AsyncJobService;
import org.onap.osam.job.impl.JobSharedData;
import org.onap.osam.job.utils.TimeUtils;

import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.Map;

@Slf4j
public abstract class BaseInProgressStatusCommand extends CommandBase implements IJobCommand {

    protected AsyncJobService asyncInstantiationBL;

    protected IJobsDataAccessService jobsDataAccessService;

    protected IJobFactory jobAdapter;

/*
    @Inject
    protected RestMsoImplementation restMso;

    @Inject
    protected AuditService auditService;
*/

    protected String requestId;

    protected String instanceId;


    @Override
    public NextCommand call() {

     //   try {
            String asyncRequestStatus = getAsyncRequestStatus();
            //asyncInstantiationBL.auditMsoStatus(getSharedData().getRootJobId(), asyncRequestStatus.get().request);
            JobStatus jobStatus = asyncInstantiationBL.calcStatus(asyncRequestStatus);
            ZonedDateTime jobStartTime = getZonedDateTime(asyncRequestStatus);
            jobStatus = isExpired(jobStartTime) ? JobStatus.FAILED : jobStatus;
            return processJobStatus(jobStatus);

            //TODO error handling
  /*      } catch (javax.ws.rs.ProcessingException e) {
            // Retry when we can't connect MSO during getStatus
            LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, will retry: {}", requestId, e, e);
            return new NextCommand(JobStatus.IN_PROGRESS, this);
        } catch (BadResponseFromMso e) {
            return handleFailedMsoResponse(e.getMsoResponse());
        }
        catch (RuntimeException e) {
            LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, stopping: {}", requestId, e, e);
            return new NextCommand(JobStatus.STOPPED, this);
        }*/
    }

    abstract NextCommand processJobStatus(JobStatus jobStatus);

    abstract boolean isExpired(ZonedDateTime jobStartTime);

    private String getAsyncRequestStatus() {
/*
        String path = asyncInstantiationBL.getOrchestrationRequestsPath()+"/"+requestId;
        RestObject<AsyncRequestStatus> msoResponse = restMso.GetForObject(path, AsyncRequestStatus.class);
        if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) {
            throw new BadResponseFromMso(msoResponse);
        }
*/
        //TODO
        return "dummy";
    }

    /*private NextCommand handleFailedMsoResponse(RestObject<AsyncRequestStatus> msoResponse) {
        auditService.setFailedAuditStatusFromMso(getSharedData().getJobUuid(), requestId, msoResponse.getStatusCode(), msoResponse.getRaw());
        LOGGER.error(EELFLoggerDelegate.errorLogger,
                "Failed to get orchestration status for {}. Status code: {},  Body: {}",
                requestId, msoResponse.getStatusCode(), msoResponse.getRaw());
        return new NextCommand(JobStatus.IN_PROGRESS, this);
    }*/

    @Override
    public BaseInProgressStatusCommand init(JobSharedData sharedData, Map<String, Object> commandData) {
        return init(sharedData, (String) commandData.get("requestId"), (String) commandData.get("instanceId"));
    }


    protected BaseInProgressStatusCommand init(JobSharedData sharedData,
                                               String requestId,
                                               String instanceId) {
        init(sharedData);
        this.requestId = requestId;
        this.instanceId = instanceId;
        return this;
    }

    @Override
    public Map<String, Object> getData() {
        return ImmutableMap.of(
            "requestId", requestId,
            "instanceId", instanceId
        );
    }

    private ZonedDateTime getZonedDateTime(String response) {
        ZonedDateTime jobStartTime;
        try {
            //TODO dummy time until real impl is provided
            jobStartTime = TimeUtils.parseZonedDateTime(ZonedDateTime.now().toString());
        } catch (DateTimeParseException | NullPointerException e) {
            log.error("Failed to parse start time for {}, body: {}. Current time will be used", requestId, response, e);
            jobStartTime = ZonedDateTime.now();
        }
        return jobStartTime;
    }
}
