/*
 * The MIT License
 *
 *   Copyright (c) 2016, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 *
 */

package io.github.benas.jpopulator.impl;

import io.github.benas.jpopulator.api.Randomizer;
import io.github.benas.jpopulator.api.Populator;
import io.github.benas.jpopulator.api.RandomizerRegistry;

import java.util.*;

/**
 * A builder to create {@link Populator} instances.
 *
 * @author Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
 */
public class PopulatorBuilder {
    /**
     * A map of custom randomizers to use to generate random values.
     */
    private Map<RandomizerDefinition, Randomizer> randomizers;

    /**
     * Set of user defined randomizer registries.
     */
    private Set<RandomizerRegistry> userRegistries;

    /**
     * Disable default registries discovered with Java Service Provider API.
     */
    private boolean defaultRegistriesDisabled;


    /**
     * Public constructor.
     */
    public PopulatorBuilder() {
        reset();
    }

    /**
     * Reset the builder to its initial state.
     */
    private void reset() {
        randomizers = new HashMap<RandomizerDefinition, Randomizer>();
        userRegistries = new LinkedHashSet<RandomizerRegistry>();
        defaultRegistriesDisabled = false;
    }

    /**
     * Register a custom randomizer for a given type and field.
     *
     * @param type       The class type for which the randomizer will be used
     * @param fieldType  the field type within the class for which the randomizer will be used
     * @param fieldName  the field name within the class for which the randomizer will be used
     * @param randomizer the custom randomizer to use
     * @return a pre configured populator builder instance
     */
    public PopulatorBuilder registerRandomizer(final Class type, final Class fieldType, final String fieldName, final Randomizer randomizer) {
        randomizers.put(new RandomizerDefinition(type, fieldType, fieldName), randomizer);
        return this;
    }

    /**
     * Register a Randomizer Registry
     *
     * @param registry the registry to register in populator
     * @return a pre configured populator builder instance
     */
    public PopulatorBuilder registerRandomizerRegistry(RandomizerRegistry registry) {
        userRegistries.add(registry);
        return this;
    };

    /**
     * Disable default randomizer registries declared through Java Service Provider API.
     *
     * @return a pre configured populator builder instance
     */
    public PopulatorBuilder disableDefaultRegistries() {
        return disableDefaultRegistries(true);
    }

    /**
     * Disable/Enable default randomizer registries declared through Java Service Provider API.
     *
     * @param disabled the disabled value of the property
     * @return a pre configured populator builder instance
     */
    public PopulatorBuilder disableDefaultRegistries(boolean disabled) {
        defaultRegistriesDisabled = disabled;
        return this;
    }

    /**
     * Build a populator instance and reset the builder to its initial state.
     *
     * @return a configured populator instance
     */
    public Populator build() {
        LinkedHashSet<RandomizerRegistry> registries = new LinkedHashSet<RandomizerRegistry>();
        registries.addAll(userRegistries);
        if (!defaultRegistriesDisabled) {
            registries.addAll(loadDefaultRegistries());
        }
        Populator populator = new PopulatorImpl(registries, randomizers);
        reset();
        return populator;
    }

    /**
     * Retrieves a collection of Randomizer Registry from Java Service Provider API.
     *
     * @return a collection of randomizer registry objects discovered from Randomizer
     */
    private Collection<? extends RandomizerRegistry> loadDefaultRegistries() {
        List<RandomizerRegistry> registries = new ArrayList<RandomizerRegistry>();
        ServiceLoader<RandomizerRegistry> loader = ServiceLoader.load(RandomizerRegistry.class);
        for (RandomizerRegistry registry : loader) {
            registries.add(registry);
        }
        return registries;
    }

}

@@ -1859,150 +1859,8 @@
 s;%0A%0A
-    /**%0A     * Disable default registries discovered with Java Service Provider API.%0A     */%0A    private boolean defaultRegistriesDisabled;%0A%0A%0A
     
@@ -2185,51 +2185,8 @@
 ();%0A
-        defaultRegistriesDisabled = false;%0A
     
@@ -2944,16 +2944,23 @@
 ister a 
+%7B@link 
 Randomiz
@@ -2961,25 +2961,24 @@
 ndomizer
- 
 Registry
 %0A     *%0A
@@ -2969,16 +2969,17 @@
 Registry
+%7D
 %0A     *%0A
@@ -3009,583 +3009,193 @@
 the 
-registry to register in populator%0A     * @return a pre configured populator builder instance%0A     */%0A    public PopulatorBuilder registerRandomizerRegistry(RandomizerRegistry registry) %7B%0A        userRegistries.add(registry);%0A        return this;%0A    %7D;%0A%0A    /**%0A     * Disable default randomizer registries declared through Java Service Provider API.%0A     *%0A     * @return a pre configured populator builder instance%0A     */%0A    public PopulatorBuilder disableDefaultRegistries() %7B%0A        return disableDefaultRegistries(true);%0A    %7D%0A%0A    /**%0A     * Disable/Enable default r
+%7B@link RandomizerRegistry%7D to register in the populator%0A     * @return a pre configured populator builder instance%0A     */%0A    public PopulatorBuilder registerRandomizerRegistry(final R
 ando
@@ -3203,313 +3203,65 @@
 izer
- r
+R
 egistr
-ies declared through Java Service Provider API.%0A     *%0A     * @param disabled the disabled value of the property%0A     * @return a pre configured populator builder instance%0A     */%0A    public PopulatorBuilder disableDefaultRegistries(boolean disabled) %7B%0A        defaultRegistriesDisabled = disabled
+y registry) %7B%0A        userRegistries.add(registry)
 ;%0A  
@@ -3607,55 +3607,50 @@
 es);
-%0A        if (!defaultRegistriesDisabled) %7B%0A    
+ // programatically registered registries%0A
     
@@ -3671,31 +3671,24 @@
 .addAll(load
-Default
 Registries()
@@ -3689,26 +3689,65 @@
 ries());
-%0A        %7D
+ // registries added to classpath through the SPI
 %0A       
@@ -3904,16 +3904,23 @@
 tion of 
+%7B@link 
 Randomiz
@@ -3925,17 +3925,16 @@
 izer
- 
 Registry
  fro
@@ -3929,16 +3929,17 @@
 Registry
+%7D
  from Ja
@@ -4001,17 +4001,24 @@
 tion of 
-r
+%7B@link R
 andomize
@@ -4018,25 +4018,25 @@
 ndomizer
- r
+R
 egistry
+%7D
  objects
@@ -4052,26 +4052,29 @@
 ed from 
-Randomizer
+the classpath
 %0A     */
@@ -4101,18 +4101,8 @@
 ion%3C
-? extends 
 Rand
@@ -4125,15 +4125,8 @@
 load
-Default
 Regi

remove defaultRegistriesDisabled option