/*-
 * ============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.services;

import org.apache.http.HttpStatus;
import org.onap.osam.aai.AaiClientInterface;
import org.onap.osam.aai.AaiResponse;
import org.onap.osam.aai.ServiceInstance;
import org.onap.osam.aai.ServiceInstancesSearchResults;
import org.onap.osam.aai.ServiceSubscription;
import org.onap.osam.aai.ServiceSubscriptions;
import org.onap.osam.aai.Services;
import org.onap.osam.aai.SubscriberFilteredResults;
import org.onap.osam.aai.model.AaiGetAicZone.AicZones;
import org.onap.osam.aai.model.AaiGetInstanceGroupsByCloudRegion;
import org.onap.osam.aai.model.AaiGetNetworkCollectionDetails.AaiGetNetworkCollectionDetails;
import org.onap.osam.aai.model.AaiGetNetworkCollectionDetails.AaiGetRelatedInstanceGroupsByVnfId;
import org.onap.osam.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList;
import org.onap.osam.aai.model.AaiGetPnfs.Pnf;
import org.onap.osam.aai.model.AaiGetServicesRequestModel.GetServicesAAIRespone;
import org.onap.osam.aai.model.AaiGetTenatns.GetTenantsResponse;
import org.onap.osam.aai.model.AaiRelationResponse;
import org.onap.osam.aai.model.InstanceGroupInfo;
import org.onap.osam.aai.model.LogicalLinkResponse;
import org.onap.osam.aai.model.Model;
import org.onap.osam.aai.model.OwningEntity;
import org.onap.osam.aai.model.OwningEntityResponse;
import org.onap.osam.aai.model.PortDetailsTranslator;
import org.onap.osam.aai.model.Project;
import org.onap.osam.aai.model.ProjectResponse;
import org.onap.osam.aai.model.RelatedToProperty;
import org.onap.osam.aai.model.Relationship;
import org.onap.osam.aai.model.RelationshipData;
import org.onap.osam.aai.model.RelationshipList;
import org.onap.osam.aai.model.ServiceRelationships;
import org.onap.osam.model.ServiceInstanceSearchResult;
import org.onap.osam.model.SubscriberList;
import org.onap.osam.roles.RoleValidator;
import org.onap.osam.utils.Intersection;
import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.core.Response;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class AaiServiceImpl implements IAaiService {
    private static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
    private static final String SERVICE_TYPE = "service-subscription.service-type";
    private static final String CUSTOMER_ID = "customer.global-customer-id";
    private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
    private int indexOfSubscriberName = 6;

    @Autowired
    private AaiClientInterface aaiClient;

    private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class);

    private boolean validateModel(Model model){
        if (model == null) {
            return false;
        } else {
            return model.getModelVers() != null && model.getModelVers().getModelVer() != null && model.getModelVers().getModelVer().get(0).getModelVersionId() != null;
        }
    }

    private List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
        AaiResponse<OwningEntityResponse> owningEntityResponse = aaiClient.getServicesByOwningEntityId(owningEntities);
        List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
        if (owningEntityResponse.getT() != null) {
            for (OwningEntity owningEntity : owningEntityResponse.getT().getOwningEntity()) {
                if (owningEntity.getRelationshipList() != null) {
                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(owningEntity, serviceInstanceSearchResultList, roleValidator);
                }
            }
        }
        return serviceInstanceSearchResultList;
    }

    private List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
        AaiResponse<ProjectResponse> projectByIdResponse = aaiClient.getServicesByProjectNames(projectNames);
        List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
        if (projectByIdResponse.getT() != null) {
            for (Project project : projectByIdResponse.getT().getProject()) {
                if (project.getRelationshipList() != null) {
                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(project, serviceInstanceSearchResultList, roleValidator);
                }
            }
        }
        return serviceInstanceSearchResultList;
    }

    private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse owningEntityResponse, List<ServiceInstanceSearchResult> serviceInstanceSearchResultList, RoleValidator roleValidator) {
        if (owningEntityResponse.getRelationshipList().getRelationship() != null) {
            List<Relationship> relationshipList = owningEntityResponse.getRelationshipList().getRelationship();
            for (Relationship relationship : relationshipList) {
                ServiceInstanceSearchResult serviceInstanceSearchResult = new ServiceInstanceSearchResult();
                extractRelationshipData(relationship, serviceInstanceSearchResult, roleValidator);
                extractRelatedToProperty(relationship, serviceInstanceSearchResult);
                serviceInstanceSearchResultList.add(serviceInstanceSearchResult);
            }
        }
        return serviceInstanceSearchResultList;
    }

    private void extractRelationshipData(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult, RoleValidator roleValidator) {
        List<RelationshipData> relationshipDataList = relationship.getRelationDataList();
        if (relationshipDataList != null) {
            setSubscriberName(relationship, serviceInstanceSearchResult);
            for (RelationshipData relationshipData : relationshipDataList) {
                String key = relationshipData.getRelationshipKey();
                if (key.equals(SERVICE_INSTANCE_ID)) {
                    serviceInstanceSearchResult.setServiceInstanceId(relationshipData.getRelationshipValue());
                } else if (key.equals(SERVICE_TYPE)) {
                    serviceInstanceSearchResult.setServiceType(relationshipData.getRelationshipValue());
                } else if (key.equals(CUSTOMER_ID)) {
                    serviceInstanceSearchResult.setGlobalCustomerId(relationshipData.getRelationshipValue());
                }
            }

            boolean isPermitted = roleValidator.isServicePermitted(serviceInstanceSearchResult.getSubscriberName(), serviceInstanceSearchResult.getServiceType());
            serviceInstanceSearchResult.setIsPermitted(isPermitted);
        }
    }

    private void setSubscriberName(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult) {
        String relatedLink = relationship.getRelatedLink();
        String[] subsciber = relatedLink.split("/");
        serviceInstanceSearchResult.setSubscriberName(subsciber[indexOfSubscriberName]);
    }

    private void extractRelatedToProperty(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult) {
        List<RelatedToProperty> relatedToPropertyList = relationship.getRelatedToPropertyList();
        if (relatedToPropertyList != null) {
            for (RelatedToProperty relatedToProperty : relatedToPropertyList) {
                if (relatedToProperty.getPropertyKey().equals(SERVICE_INSTANCE_NAME)) {
                    serviceInstanceSearchResult.setServiceInstanceName(relatedToProperty.getPropertyValue());
                }
            }
        }
    }

    @Override
    public SubscriberFilteredResults getFullSubscriberList(RoleValidator roleValidator) {
        AaiResponse<SubscriberList> subscriberResponse = aaiClient.getAllSubscribers();

        return new SubscriberFilteredResults(roleValidator, subscriberResponse.getT(),
                subscriberResponse.getErrorMessage(),
                subscriberResponse.getHttpCode());
    }

    @Override
    public AaiResponse<OperationalEnvironmentList> getOperationalEnvironments(String operationalEnvironmentType, String operationalEnvironmentStatus) {
        return aaiClient.getOperationalEnvironments(operationalEnvironmentType, operationalEnvironmentStatus);
    }

    @Override
    public AaiResponse<SubscriberList> getFullSubscriberList() {
        return aaiClient.getAllSubscribers();
    }

    @Override
    public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator) {
        AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId);
        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
        for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) {
            String serviceType = serviceSubscription.serviceType;
            serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
        }
        return subscriberResponse;

    }

    @Override
    public AaiResponse getServiceInstanceSearchResults(String subscriberId, String instanceIdentifier, RoleValidator roleValidator, List<String> owningEntities, List<String> projects) {
        List<List<ServiceInstanceSearchResult>> resultList = new ArrayList<>();
        ServiceInstancesSearchResults serviceInstancesSearchResults = new ServiceInstancesSearchResults();

        if (subscriberId != null || instanceIdentifier != null) {
            resultList.add(getServicesBySubscriber(subscriberId, instanceIdentifier, roleValidator));
        }
        if (owningEntities != null) {
            resultList.add(getServicesByOwningEntityId(owningEntities, roleValidator));
        }
        if (projects != null) {
            resultList.add(getServicesByProjectNames(projects, roleValidator));
        }
        if (!resultList.isEmpty()) {
            Intersection<ServiceInstanceSearchResult> intersection = new Intersection<>();
            serviceInstancesSearchResults.serviceInstances = intersection.intersectMultipileArray(resultList);
        }

        return new AaiResponse<>(serviceInstancesSearchResults, null, HttpStatus.SC_OK);
    }


    private List<ServiceInstanceSearchResult> getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) {
        AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId);
        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
        String subscriberName = subscriberResponse.getT().subscriberName;
        ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions;

        return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberGlobalId, subscriberName);

    }


    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier, RoleValidator roleValidator, String subscriberGlobalId, String subscriberName) {
        ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();

        if (serviceSubscriptions != null) {
            for (ServiceSubscription serviceSubscription : serviceSubscriptions.serviceSubscription) {
                String serviceType = serviceSubscription.serviceType;
                serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
                ArrayList<ServiceInstanceSearchResult> resultsForSubscription = getSearchResultsForSingleSubscription(serviceSubscription, subscriberId, instanceIdentifier, subscriberName, serviceType);
                results.addAll(resultsForSubscription);
            }
        }

        return results;
    }

    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName, String serviceType) {
        ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();

        if (serviceSubscription.serviceInstances != null) {
            for (ServiceInstance serviceInstance : serviceSubscription.serviceInstances.serviceInstance) {
                ServiceInstanceSearchResult serviceInstanceSearchResult =
                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName,
                                subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, serviceSubscription.isPermitted);

                if (instanceIdentifier == null) {
                    results.add(serviceInstanceSearchResult);
                } else if (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance)) {
                    results.add(serviceInstanceSearchResult);
                }
            }
        }

        return results;
    }

    private boolean serviceInstanceMatchesIdentifier(String instanceIdentifier, ServiceInstance serviceInstance) {
        return instanceIdentifier.equals(serviceInstance.serviceInstanceId) || instanceIdentifier.equals(serviceInstance.serviceInstanceName);
    }

    @Override
    public Response getVersionByInvariantId(List<String> modelInvariantId) {
        try {
            return aaiClient.getVersionByInvariantId(modelInvariantId);
        } catch (Exception e) {
            LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e);
        }
        return null;
    }

    @Override
    public AaiResponse<Pnf> getSpecificPnf(String pnfId) {
        return aaiClient.getSpecificPnf(pnfId);
    }

    @Override
    public AaiResponse getPNFData(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion, String equipVendor, String equipModel) {
        return aaiClient.getPNFData(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion, equipVendor, equipModel);
    }



    @Override
    public AaiResponse getServices(RoleValidator roleValidator) {
        AaiResponse<GetServicesAAIRespone> subscriberResponse = aaiClient.getServices();
        if (subscriberResponse.getT() != null) {
            for (org.onap.osam.aai.model.AaiGetServicesRequestModel.Service service : subscriberResponse.getT().service) {
                service.isPermitted = true;
            }
        }
        return subscriberResponse;
    }

    @Override
    public AaiResponse<GetTenantsResponse[]> getTenants(String globalCustomerId, String serviceType, RoleValidator roleValidator) {
        AaiResponse<GetTenantsResponse[]> aaiGetTenantsResponse = aaiClient.getTenants(globalCustomerId, serviceType);
        GetTenantsResponse[] tenants = aaiGetTenantsResponse.getT();
        if (tenants != null) {
            for (int i = 0; i < tenants.length; i++) {
                tenants[i].isPermitted = roleValidator.isTenantPermitted(globalCustomerId, serviceType, tenants[i].tenantName);
            }
        }
        return aaiGetTenantsResponse;


    }

    @Override
    public AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId) {
        return aaiClient.getVNFData(globalSubscriberId, serviceType, serviceInstanceId);
    }

    @Override
    public Response getVNFData(String globalSubscriberId, String serviceType) {
        return aaiClient.getVNFData(globalSubscriberId, serviceType);
    }

    @Override
    public AaiResponse getAaiZones() {
        return (AaiResponse<AicZones>) aaiClient.getAllAicZones();
    }

    @Override
    public AaiResponse getAicZoneForPnf(String globalCustomerId, String serviceType, String serviceId) {
        String aicZone = "";

        AaiResponse<ServiceRelationships> serviceInstanceResp = aaiClient.getServiceInstance(globalCustomerId, serviceType, serviceId);
        if (serviceInstanceResp.getT() != null) {
            List<String> aicZoneList = getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "zone", "zone.zone-id");
            if (!aicZoneList.isEmpty()) {
                aicZone = aicZoneList.get(0);
            } else {
                LOGGER.warn("aic zone not found for service instance " + serviceId);
            }
        } else {
            if (serviceInstanceResp.getErrorMessage() != null) {
                LOGGER.error("get service instance {} return error {}", serviceId, serviceInstanceResp.getErrorMessage());
                return new AaiResponse(aicZone , serviceInstanceResp.getErrorMessage() ,serviceInstanceResp.getHttpCode());
            } else {
                LOGGER.warn("get service instance {} return empty body", serviceId);
                return new AaiResponse(aicZone , "get service instance " + serviceId + " return empty body" ,serviceInstanceResp.getHttpCode());
            }
        }

        return new AaiResponse(aicZone , null ,HttpStatus.SC_OK);
    }

    @Override
    public AaiResponse getNodeTemplateInstances(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion) {
        return aaiClient.getNodeTemplateInstances(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion);
    }

    @Override
    public AaiResponse getNetworkCollectionDetails(String serviceInstanceId){
        AaiResponse<AaiGetNetworkCollectionDetails> getNetworkCollectionDetailsAaiResponse = aaiClient.getNetworkCollectionDetails(serviceInstanceId);
        return getNetworkCollectionDetailsAaiResponse;
    }

    @Override
    public AaiResponse<AaiGetInstanceGroupsByCloudRegion> getInstanceGroupsByCloudRegion(String cloudOwner, String cloudRegionId, String networkFunction){
        AaiResponse<AaiGetInstanceGroupsByCloudRegion> getInstanceGroupsByCloudRegionResponse = aaiClient.getInstanceGroupsByCloudRegion(cloudOwner, cloudRegionId, networkFunction);
        return getInstanceGroupsByCloudRegionResponse;
    }

     @Override
    public List<String> getServiceInstanceAssociatedPnfs(String globalCustomerId, String serviceType, String serviceInstanceId) {
        List<String> pnfs = new ArrayList<>();

        AaiResponse<ServiceRelationships> serviceInstanceResp = aaiClient.getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
        if (serviceInstanceResp.getT() != null) {

            addPnfsToListViaLogicalLinks(pnfs, serviceInstanceResp);
            addPnfsToListViaDirectRelations(pnfs, serviceInstanceResp);

            if (pnfs.isEmpty()) {
                LOGGER.warn("no pnf direct relation found for service id:" + serviceInstanceId+
                        " name: "+serviceInstanceResp.getT().getServiceInstanceName());
            }
        } else {
            if (serviceInstanceResp.getErrorMessage() != null) {
                LOGGER.error("get service instance {} return error {}", serviceInstanceId, serviceInstanceResp.getErrorMessage());
            } else {
                LOGGER.warn("get service instance {} return empty body", serviceInstanceId);
            }
        }

        return pnfs.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public AaiResponse getInstanceGroupsByVnfInstanceId(String vnfInstanceId){
        AaiResponse<AaiGetRelatedInstanceGroupsByVnfId> aaiResponse = aaiClient.getInstanceGroupsByVnfInstanceId(vnfInstanceId);
        if(aaiResponse.getHttpCode() == HttpStatus.SC_OK){
            return new AaiResponse(convertGetInstanceGroupsResponseToSimpleResponse(aaiResponse.getT()), aaiResponse.getErrorMessage(), aaiResponse.getHttpCode());
        }
        return aaiClient.getInstanceGroupsByVnfInstanceId(vnfInstanceId);
    }

    private List<InstanceGroupInfo> convertGetInstanceGroupsResponseToSimpleResponse(AaiGetRelatedInstanceGroupsByVnfId response) {
        List<InstanceGroupInfo> instanceGroupInfoList = new ArrayList<>();
        for(org.onap.osam.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship: response.getRelationshipList().getRelationship()){
            getInstanceGroupInfoFromRelationship(relationship, instanceGroupInfoList);
        }
        return instanceGroupInfoList;
    }

    private void getInstanceGroupInfoFromRelationship(org.onap.osam.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship, List<InstanceGroupInfo> instanceGroupInfoList) {
        if(relationship.getRelatedTo().equals("instance-group")){
            for(org.onap.osam.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty relatedToProperty: relationship.getRelatedToPropertyList()){
                if(relatedToProperty.getPropertyKey().equals("instance-group.instance-group-name")){
                    instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getPropertyValue()));
                }
            }
        }
    }

    @Override
    public  List<PortDetailsTranslator.PortDetails> getPortMirroringSourcePorts(String configurationId){
        return aaiClient.getPortMirroringSourcePorts(configurationId);
    }

    private void addPnfsToListViaDirectRelations(List<String> pnfs, AaiResponse<ServiceRelationships> serviceInstanceResp) {
        pnfs.addAll(getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "pnf", "pnf.pnf-name"));
    }

    private void addPnfsToListViaLogicalLinks(List<String> pnfs, AaiResponse<ServiceRelationships> serviceInstanceResp) {
        List<String> logicalLinks = getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "logical-link", "logical-link.link-name");
        for (String logicalLink : logicalLinks) {
            String link;
            try {
                link = URLEncoder.encode(logicalLink, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                LOGGER.error("Failed to encode logical link: " + logicalLink, e);
                continue;
            }

            AaiResponse<LogicalLinkResponse> logicalLinkResp = aaiClient.getLogicalLink(link);
            if (logicalLinkResp.getT() != null) {
                //lag-interface is the key for pnf - approved by Bracha
                List<String> linkPnfs = getRelationshipDataByType(logicalLinkResp.getT().getRelationshipList(), "lag-interface", "pnf.pnf-name");
                if (!linkPnfs.isEmpty()) {
                    pnfs.addAll(linkPnfs);
                } else {
                    LOGGER.warn("no pnf found for logical link " + logicalLink);
                }
            } else {
                if (logicalLinkResp.getErrorMessage() != null) {
                    LOGGER.error("get logical link " + logicalLink + " return error", logicalLinkResp.getErrorMessage());
                } else {
                    LOGGER.warn("get logical link " + logicalLink + " return empty body");
                }
            }
        }
    }

    private List<String> getRelationshipDataByType(RelationshipList relationshipList, String relationshipType, String relationshipDataKey) {
        List<String> relationshipValues = new ArrayList<>();
        for (Relationship relationship : relationshipList.getRelationship()) {
            if (relationship.getRelatedTo().equals(relationshipType)) {
                relationshipValues.addAll( relationship.getRelationDataList().stream()
                        .filter(rel -> rel.getRelationshipKey().equals(relationshipDataKey))
                        .map(RelationshipData::getRelationshipValue)
                        .collect(Collectors.toList())
                );
            }
        }


        return relationshipValues;
    }
}
