/**
 * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.hawkbit.mgmt.rest.resource;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetType;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.springframework.util.CollectionUtils;

/**
 * A mapper which maps repository model to RESTful model representation and
 * back.
 *
 */
final class MgmtDistributionSetTypeMapper {

    // private constructor, utility class
    private MgmtDistributionSetTypeMapper() {

    }

    static List<DistributionSetType> smFromRequest(final EntityFactory entityFactory,
            final SoftwareManagement softwareManagement,
            final Iterable<MgmtDistributionSetTypeRequestBodyPost> smTypesRest) {
        final List<DistributionSetType> mappedList = new ArrayList<>();

        for (final MgmtDistributionSetTypeRequestBodyPost smRest : smTypesRest) {
            mappedList.add(fromRequest(entityFactory, softwareManagement, smRest));
        }
        return mappedList;
    }

    static DistributionSetType fromRequest(final EntityFactory entityFactory,
            final SoftwareManagement softwareManagement, final MgmtDistributionSetTypeRequestBodyPost smsRest) {

        final DistributionSetType result = entityFactory.generateDistributionSetType(smsRest.getKey(),
                smsRest.getName(), smsRest.getDescription());

        // Add mandatory
        if (!CollectionUtils.isEmpty(smsRest.getMandatorymodules())) {
            smsRest.getMandatorymodules().stream().map(mand -> {
                final SoftwareModuleType smType = softwareManagement.findSoftwareModuleTypeById(mand.getId());

                if (smType == null) {
                    throw new EntityNotFoundException("SoftwareModuleType with ID " + mand.getId() + " not found");
                }

                return smType;
            }).forEach(result::addMandatoryModuleType);
        }

        // Add optional
        if (!CollectionUtils.isEmpty(smsRest.getOptionalmodules())) {
            smsRest.getOptionalmodules().stream().map(opt -> {
                final SoftwareModuleType smType = softwareManagement.findSoftwareModuleTypeById(opt.getId());

                if (smType == null) {
                    throw new EntityNotFoundException("SoftwareModuleType with ID " + opt.getId() + " not found");
                }

                return smType;
            }).forEach(result::addOptionalModuleType);
        }

        return result;
    }

    static List<MgmtDistributionSetType> toTypesResponse(final List<DistributionSetType> types) {
        final List<MgmtDistributionSetType> response = new ArrayList<>();
        for (final DistributionSetType dsType : types) {
            response.add(toResponse(dsType));
        }
        return response;
    }

    static List<MgmtDistributionSetType> toListResponse(final List<DistributionSetType> types) {
        final List<MgmtDistributionSetType> response = new ArrayList<>();
        for (final DistributionSetType dsType : types) {
            response.add(toResponse(dsType));
        }
        return response;
    }

    static MgmtDistributionSetType toResponse(final DistributionSetType type) {
        final MgmtDistributionSetType result = new MgmtDistributionSetType();

        MgmtRestModelMapper.mapNamedToNamed(result, type);
        result.setKey(type.getKey());
        result.setModuleId(type.getId());

        result.add(linkTo(methodOn(MgmtDistributionSetTypeRestApi.class).getDistributionSetType(result.getModuleId()))
                .withRel("self"));

        result.add(linkTo(methodOn(MgmtDistributionSetTypeRestApi.class).getMandatoryModules(result.getModuleId()))
                .withRel(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULES));

        result.add(linkTo(methodOn(MgmtDistributionSetTypeRestApi.class).getOptionalModules(result.getModuleId()))
                .withRel(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULES));

        return result;
    }

}

@@ -2374,24 +2374,351 @@
     
-// Add mandatory
+addMandatoryModules(softwareManagement, smsRest, result);%0A        addOptionalModules(softwareManagement, smsRest, result);%0A%0A        return result;%0A    %7D%0A%0A    private static void addOptionalModules(final SoftwareManagement softwareManagement,%0A            final MgmtDistributionSetTypeRequestBodyPost smsRest, final DistributionSetType result) %7B
 %0A   
@@ -2758,33 +2758,32 @@
 (smsRest.get
-Mandatory
+Optional
 modules())) 
@@ -2807,25 +2807,24 @@
 Rest.get
-Mandatory
+Optional
 modules(
@@ -2838,20 +2838,19 @@
 m().map(
-mand
+opt
  -%3E %7B%0A  
@@ -2943,20 +2943,19 @@
 ypeById(
-mand
+opt
 .getId()
@@ -3086,12 +3086,11 @@
 %22 + 
-mand
+opt
 .get
@@ -3195,25 +3195,24 @@
 ult::add
-Mandatory
+Optional
 ModuleTy
@@ -3230,32 +3230,205 @@
   %7D%0A
-%0A
     
+%7D%0A%0A
     
-// Add optional
+private static void addMandatoryModules(final SoftwareManagement softwareManagement,%0A            final MgmtDistributionSetTypeRequestBodyPost smsRest, final DistributionSetType result) %7B
 %0A   
@@ -3468,32 +3468,33 @@
 (smsRest.get
-Optional
+Mandatory
 modules())) 
@@ -3514,32 +3514,33 @@
  smsRest.get
-Optional
+Mandatory
 modules().st
@@ -3542,35 +3542,36 @@
 ().stream().map(
-opt
+mand
  -%3E %7B%0A          
@@ -3648,35 +3648,36 @@
 eModuleTypeById(
-opt
+mand
 .getId());%0A%0A    
@@ -3788,35 +3788,36 @@
 ype with ID %22 + 
-opt
+mand
 .getId() + %22 not
@@ -3906,32 +3906,33 @@
 (result::add
-Optional
+Mandatory
 ModuleType);
@@ -3945,32 +3945,8 @@
    %7D
-%0A%0A        return result;
 %0A   

Improve readability