/*-
 * ============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.impl;

import com.google.common.collect.ImmutableMap;
import org.onap.osam.job.dao.job.JobStatus;
import org.onap.osam.job.dao.job.OsamJob;
import org.onap.osam.job.AsyncJobService;
import org.onap.osam.job.JobType;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class AsyncJobServiceImpl implements AsyncJobService {

    private final JobFactory jobFactory;

    private final JobsDataAccessService jobsDataAccessService;

    private Map<String, JobStatus> msoStateToJobStatusMap = ImmutableMap.<String, JobStatus>builder()
            .put("inprogress", JobStatus.IN_PROGRESS)
            .put("failed", JobStatus.FAILED)
            .put("pause", JobStatus.PAUSE)
            .put("paused", JobStatus.PAUSE)
            .put("complete", JobStatus.COMPLETED)
            .put("pending", JobStatus.IN_PROGRESS)
            .put("pendingmanualtask", JobStatus.PAUSE)
            .put("unlocked", JobStatus.IN_PROGRESS)
            .build();


    public AsyncJobServiceImpl(JobFactory jobFactory, JobsDataAccessService jobsDataAccessService) {
        this.jobFactory = jobFactory;
        this.jobsDataAccessService = jobsDataAccessService;
    }

    @Override
    public JobStatus calcStatus(String asyncRequestStatus) {
        JobStatus jobStatus = msoStateToJobStatusMap.get(asyncRequestStatus);
        return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS);
    }

    @Override
    public List<UUID> pushBulkJob(String userId, boolean isSuccessful, boolean isOltDependant) {
        List<UUID> uuids = new ArrayList<>();
        Date createdBulkDate = Calendar.getInstance().getTime();
        int bulkSize = 1;
        for (int i = 0; i < bulkSize; i++) {
            OsamJob job = jobFactory.createRootJob(JobType.ChassisCreation, new DummyAsyncRequest(), userId, i,
                    ImmutableMap.of("isSuccessful", isSuccessful, "isOltDependant", isOltDependant));
            UUID jobId = jobsDataAccessService.add(job);
            uuids.add(jobId);
        }
        return uuids;
    }



/*
    private final DataAccessService dataAccessService;

    private final IJobFactory jobAdapter;

    private final IJobsDataAccessService jobService;

    private SessionFactory sessionFactory;

    private AaiClientInterface aaiClient;

    private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI;

    private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class);



    @Autowired
    public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService,
                                               IJobFactory jobAdapter,
                                               IJobsDataAccessService jobService,
                                               SessionFactory sessionFactory,
                                               AaiClientInterface aaiClient) {
        this.dataAccessService = dataAccessService;
        this.jobAdapter = jobAdapter;
        this.jobService = jobService;
        this.sessionFactory = sessionFactory;
        this.aaiClient = aaiClient;
    }

    @Override
    public List<ServiceInfo> getAllServicesInfo() {
        return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null);
    }

    private String filterByCreationDateAndNotDeleted() {
        LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3);
        Timestamp filterDate = Timestamp.valueOf(minus3Months);
        return " where" +
                "   hidden = false" +
                "   and deleted_at is null" +  // don't fetch deleted
                "   and created >= '" + filterDate + "' ";
    }

    private String orderByCreatedDateAndStatus() {
        return " createdBulkDate DESC ,\n" +
                "  (CASE jobStatus\n" +
                "   WHEN 'COMPLETED' THEN 0\n" +
                "   WHEN 'FAILED' THEN 0\n" +
                "   WHEN 'IN_PROGRESS' THEN 1\n" +
                "   WHEN 'PAUSE' THEN 2\n" +
                "   WHEN 'PENDING' THEN 3\n" +
                "   WHEN 'STOPPED' THEN 3 END),\n" +
                "  statusModifiedDate ";
    }

    @Override
    public List<UUID> pushBulkJob(ServiceInstantiation request, String userId) {
        List<UUID> uuids = new ArrayList<>();
        Date createdBulkDate = Calendar.getInstance().getTime();
        int bulkSize = request.getBulkSize();
        UUID templateId = UUID.randomUUID();
        for (int i = 0; i < bulkSize; i++) {
            //Job job = jobAdapter.createJob(JobType.ServiceInstantiation, request, templateId, userId, i);
            Job job = jobAdapter.createJob(JobType.NoOp, request, templateId, userId, i);//should be some instatiation, this was changed as part of code cleaning

            UUID jobId = jobService.add(job);
            auditVidStatus(jobId,getStatus());
            uuids.add(jobId);
            dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate), DaoUtils.getPropsMap());
        }
        return uuids;
    }

    private ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate) {
        return new ServiceInfo(
                userId, JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId,
                serviceInstantiation.getOwningEntityId(),
                serviceInstantiation.getOwningEntityName(),
                serviceInstantiation.getProjectName(),
                serviceInstantiation.getAicZoneId(),
                serviceInstantiation.getAicZoneName(),
                serviceInstantiation.getTenantId(),
                serviceInstantiation.getTenantName(),
                serviceInstantiation.getLcpCloudRegionId(),
                null,
                serviceInstantiation.getSubscriptionServiceType(),
                serviceInstantiation.getSubscriberName(),
                null,
                serviceInstantiation.getInstanceName(),
                serviceInstantiation.getModelInfo().getModelInvariantId(),
                serviceInstantiation.getModelInfo().getModelName(),
                serviceInstantiation.getModelInfo().getModelVersion(),
                createdBulkDate
        );
    }


    */
/*//*
/@Override
    public RequestDetailsWrapper<ServiceInstantiationRequestDetails> generateServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String userId) {

           ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName());

        SubscriberInfo subscriberInfo = new SubscriberInfo();
        subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId());

        String serviceInstanceName = null;
        if(payload.isUserProvidedNaming()) {
            serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE);
            String finalServiceInstanceName = serviceInstanceName;
            updateServiceInfo(jobId, x -> x.setServiceInstanceName(finalServiceInstanceName));
        }
        ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(
                serviceInstanceName,
                payload.getProductFamilyId(),
                "VID",
                payload.isRollbackOnFailure(),
                userId);

        List<ServiceInstantiationRequestDetails.ServiceInstantiationService> serviceInstantiationService = new LinkedList<>();
        List<Map<String, String>> unFilteredInstanceParams = payload.getInstanceParams() != null ? payload.getInstanceParams() : new LinkedList<>();
        List<Map<String, String>> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams);
        ServiceInstantiationRequestDetails.ServiceInstantiationService serviceInstantiationService1 = new ServiceInstantiationRequestDetails.ServiceInstantiationService(
                payload.getModelInfo(),
                serviceInstanceName,
                filteredInstanceParams,
                createServiceInstantiationVnfList(payload)
        );
        serviceInstantiationService.add(serviceInstantiationService1);

        ServiceInstantiationRequestDetails.RequestParameters requestParameters = new ServiceInstantiationRequestDetails.RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationService);

        ServiceInstantiationRequestDetails.Project project = payload.getProjectName() != null ?  new ServiceInstantiationRequestDetails.Project(payload.getProjectName()) : null;

        ServiceInstantiationRequestDetails requestDetails = new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo,
                project, requestInfo, requestParameters);

        RequestDetailsWrapper<ServiceInstantiationRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper(requestDetails);
        debugRequestDetails(requestDetailsWrapper, logger);
        return requestDetailsWrapper;
    }*//*


    private List<Map<String, String>> removeUnNeededParams(List<Map<String, String>> instanceParams) {
        List<String> keysToRemove = new ArrayList<>();
        if (instanceParams != null && !instanceParams.isEmpty()) {
            for (String key : instanceParams.get(0).keySet()) {
                for (String paramToIgnore : PARAMS_TO_IGNORE)
                    if ((key.equalsIgnoreCase(paramToIgnore))) {
                        keysToRemove.add(key);
                    }
            }
            for (String key : keysToRemove) {
                instanceParams.get(0).remove(key);
            }
            //TODO will be removed on once we stop using List<Map<String, String>>
            if (instanceParams.get(0).isEmpty()) {
                return Collections.emptyList();
            }
        }
        return instanceParams;
    }

    private ServiceInstantiationRequestDetails.ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) {
        CloudConfiguration cloudConfiguration = new CloudConfiguration();
        cloudConfiguration.setTenantId(payload.getTenantId());
        cloudConfiguration.setLcpCloudRegionId(payload.getLcpCloudRegionId());

        Map<String, Vnf> vnfs = payload.getVnfs();
        List<ServiceInstantiationRequestDetails.ServiceInstantiationVnf> vnfList = new ArrayList<>();
        for (Vnf vnf : vnfs.values()) {
            Map<String, Map<String, VfModule>> vfModules = vnf.getVfModules();
            List<VfModule> convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules);
            List<VfModule> filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules, vnf.isUserProvidedNaming());
            ServiceInstantiationRequestDetails.ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationRequestDetails.ServiceInstantiationVnf(
                    vnf.getModelInfo(),
                    cloudConfiguration,
                    vnf.getPlatformName(),
                    vnf.getLineOfBusiness(),
                    payload.getProductFamilyId(),
                    removeUnNeededParams(vnf.getInstanceParams()),
                    filteredVfModules,
                    vnf.isUserProvidedNaming() ? getUniqueName(vnf.getInstanceName(), ResourceType.GENERIC_VNF) : null
            );
            vnfList.add(serviceInstantiationVnf);
        }

        return new ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList);
    }

    private List<VfModule> convertVfModuleMapToList(Map<String, Map<String, VfModule>> vfModules) {
        return vfModules.values().stream().flatMap(vfModule -> vfModule.values().stream()).collect(Collectors.toList());
    }

    private List<VfModule> filterInstanceParamsFromVfModuleAndUniqueNames(List<VfModule> unFilteredVfModules, boolean isUserProvidedNaming) {
        return unFilteredVfModules.stream().map(vfModule ->
                new VfModule(
                        vfModule.getModelInfo(),
                        getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getInstanceName(), ResourceType.VF_MODULE),
                        getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP),
                        removeUnNeededParams(vfModule.getInstanceParams())))
                .collect(Collectors.toList());
    }

    private String getUniqueNameIfNeeded(boolean isUserProvidedNaming, String name, ResourceType resourceType) {
        return isUserProvidedNaming && !StringUtils.isEmpty(name) ?
                getUniqueName(name, resourceType) : null;
    }

    @Override
    public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) {
        //in case pause flag is true - use assign , else - use create.
        return MsoBusinessLogicImpl.validateEndpointPath(
                serviceInstantiationRequest.isPause() ?
                        "mso.restapi.serviceInstanceAssign" : "mso.restapi.serviceInstanceCreate"
        );
    }

    @Override
    public String getOrchestrationRequestsPath() {
        return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ);
    }

    @Override
    public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer<ServiceInfo> serviceUpdater) {
        ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
        serviceUpdater.accept(serviceInfo);
        dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
        return serviceInfo;
    }



    private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) {
        serviceInfo.setJobStatus(jobStatus);
        serviceInfo.setStatusModifiedDate(new Date());
    }

    public ServiceInfo getServiceInfoByJobId(UUID jobUUID) {
        List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null);
        if (serviceInfoList.size() != 1) {
            throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size());
        }
        return serviceInfoList.get(0);
    }

    public List<JobAuditStatus> getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) {
        return dataAccessService.getList(
            JobAuditStatus.class,
            String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID),
            " CREATED_DATE ", null);
    }

    private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){
        List<JobAuditStatus> list = getAuditStatuses(jobUUID,source);
        return !list.isEmpty() ? list.get(list.size()-1) : null;
    }

    @Override
    public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){
        JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID);
        auditStatus(vidStatus);
    }

    @Override
    public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){
        auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage());
    }

    @Override
    public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){
        JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO,
                requestId != null ? UUID.fromString(requestId) : null,
                additionalInfo);
        auditStatus(msoStatus);
    }

    private void auditStatus(JobAuditStatus jobAuditStatus){
        JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(),jobAuditStatus.getSource());
        if (latestStatus == null || !latestStatus.equals(jobAuditStatus))
            dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap());

    }



    @Override
    public void handleFailedInstantiation(UUID jobUUID) {
        ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED);
        List<ServiceInfo> serviceInfoList = dataAccessService.getList(
                ServiceInfo.class,
                String.format(" where templateId = '%s' and jobStatus = '%s'",
                        serviceInfo.getTemplateId(),
                        JobStatus.PENDING),
                null, null);
        serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED));
    }

    @Override
    public void deleteJob(UUID jobId) {
        jobService.delete(jobId);
        Date now = new Date();
        updateServiceInfo(jobId, x -> x.setDeletedAt(now));
    }

    @Override
    public void hideServiceInfo(UUID jobUUID) {
        ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
        if (!serviceInfo.getJobStatus().isFinal()) {
            String message = String.format( "jobId %s: Service status does not allow hide service, status = %s",
                    serviceInfo.getJobId(),
                    serviceInfo.getJobStatus());
            logger.error(EELFLoggerDelegate.errorLogger, message);
            throw new OperationNotAllowedException(message);
        }
        serviceInfo.setHidden(true);
        dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
    }

    @Override
    public int


    getCounterForName(String name) {

        String hqlSelectNC = "from NameCounter where name = :name";
        String hqlUpdateCounter = "update NameCounter set counter = :newCounter " +
                "where name= :name " +
                "and counter= :prevCounter";

        Integer counter = null;
        GenericUncheckedException lastException = null;
        for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) {
            try {
                counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter);
            }
            catch (GenericUncheckedException exception) {
                lastException = exception; //do nothing, we will try again in the loop
            }
        }

        if (counter!=null) {
            return counter;
        }

        throw lastException!=null ? new DbFailureUncheckedException(lastException) :
                new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error");

    }

    private Integer calcCounter(String name, String hqlSelectNC, String hqlUpdateCounter) {
        Integer counter;
        counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> {
            NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC)
                    .setText("name", name)
                    .uniqueResult();
            if (nameCounter != null) {
                int updatedRows = session.createQuery(hqlUpdateCounter)
                        .setText("name", nameCounter.getName())
                        .setInteger("prevCounter", nameCounter.getCounter())
                        .setInteger("newCounter", nameCounter.getCounter() + 1)
                        .executeUpdate();
                if (updatedRows == 1) {
                    return nameCounter.getCounter() + 1;
                }
            } else {
                Object nameAsId = session.save(new NameCounter(name));
                //if save success
                if (nameAsId != null) {
                    return 1;
                }
            }
            //in case of failure return null, in order to continue the loop
            return null;
        });
        return counter;
    }

    @Override
    public int getMaxRetriesGettingFreeNameFromAai() {
        return maxRetriesGettingFreeNameFromAai;
    }

    @Override
    public void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai) {
        this.maxRetriesGettingFreeNameFromAai = maxRetriesGettingFreeNameFromAai;
    }

    @Override
    public String getUniqueName(String name, ResourceType resourceType) {
        //check that name aai response well before increasing counter from DB
        //Prevents unnecessary increasing of the counter while AAI doesn't response
        isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType);

        for (int i=0; i<getMaxRetriesGettingFreeNameFromAai(); i++) {
            int counter = getCounterForName(name);
            String newName = formatNameAndCounter(name, counter);
            if (isNameFreeInAai(newName, resourceType)) {
                return newName;
            }
        }

        throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai());
    }

    //the method is protected so we can call it in the UT
    protected String formatNameAndCounter(String name, int counter) {
        return name + "_" + String.format("%03d", counter);
    }

    private boolean isNameFreeInAai(String name, ResourceType resourceType) throws InvalidAAIResponseException {
        AaiResponse<AaiNodeQueryResponse> aaiResponse = aaiClient.searchNodeTypeByName(name, resourceType);
        if (aaiResponse.getHttpCode() > 399 || aaiResponse.getT() == null) {
            throw new InvalidAAIResponseException(aaiResponse);
        }
        return CollectionUtils.isEmpty(aaiResponse.getT().resultData);
    }
*/

}
