/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org. 
 */

package org.openlmis.referencedata.validate;

import org.openlmis.referencedata.dto.FacilityDto;
import org.openlmis.referencedata.dto.SupportedProgramDto;
import org.openlmis.referencedata.exception.ValidationMessageException;
import org.openlmis.referencedata.repository.FacilityRepository;
import org.openlmis.referencedata.util.messagekeys.FacilityMessageKeys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;

import java.util.Set;

@Component
public class FacilityValidator implements BaseValidator {

  protected static final String CODE = "code";

  @Autowired
  private FacilityRepository facilityRepository;

  @Override
  public boolean supports(Class<?> clazz) {
    return FacilityDto.class.equals(clazz);
  }

  @Override
  public void validate(Object target, Errors errors) {
    verifyArguments(target, errors, FacilityMessageKeys.ERROR_NULL);
    rejectIfEmptyOrWhitespace(errors, CODE, FacilityMessageKeys.ERROR_CODE_REQUIRED);

    FacilityDto facilityDto = (FacilityDto) target;
    if (facilityRepository.existsByCode(facilityDto.getCode())
            && (facilityDto.getId() == null
            || !facilityRepository.findFirstByCode(facilityDto.getCode()).getId()
            .equals(facilityDto.getId()))) {
      rejectValue(errors, CODE, FacilityMessageKeys.ERROR_CODE_MUST_BE_UNIQUE);
    }

    validateDuplicateProgramSupported(facilityDto.getSupportedPrograms());
  }

  private void validateDuplicateProgramSupported(Set<SupportedProgramDto> supportedProgramDtos) {
    if (supportedProgramDtos != null
          &&  (supportedProgramDtos.stream()
              .map(SupportedProgramDto::getCode)
              .distinct()
              .count() != supportedProgramDtos.size()
          || supportedProgramDtos.stream()
                  .map(SupportedProgramDto::getId)
                  .distinct()
                  .count() != supportedProgramDtos.size())) {
      throw new ValidationMessageException(FacilityMessageKeys.ERROR_DUPLICATE_PROGRAM_SUPPORTED);
    }
  }
}

@@ -2277,16 +2277,72 @@
 %0A    %7D%0A%0A
+    if (facilityDto.getSupportedPrograms() != null) %7B%0A  
     vali
@@ -2408,16 +2408,22 @@
 ams());%0A
+    %7D%0A
   %7D%0A%0A  p
@@ -2525,56 +2525,37 @@
     
-if (suppor
+boolean duplica
 te
-d
 Program
-Dtos != null%0A          &&  (
+Id = 
 supp
@@ -2572,34 +2572,32 @@
 amDtos.stream()%0A
-  
             .map
@@ -2631,34 +2631,32 @@
 de)%0A            
- 
- 
 .distinct()%0A    
@@ -2643,34 +2643,32 @@
     .distinct()%0A
-  
             .cou
@@ -2706,21 +2706,45 @@
 ze()
+;%0A
 %0A    
-      %7C%7C
+boolean duplicateProgramCode =
  sup
@@ -2778,30 +2778,24 @@
             
-   
-   
 .map(Support
@@ -2823,30 +2823,24 @@
             
-      
 .distinct()%0A
@@ -2847,30 +2847,24 @@
             
-     
- 
 .count() != 
@@ -2890,17 +2890,70 @@
 s.size()
-)
+;%0A%0A    if (duplicateProgramId  %7C%7C duplicateProgramCode
 ) %7B%0A    

refactor facility supported program validation