/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.spine3.examples.todolist.context;

import com.google.common.annotations.VisibleForTesting;
import org.spine3.examples.todolist.repository.DraftTasksViewRepository;
import org.spine3.examples.todolist.repository.LabelAggregateRepository;
import org.spine3.examples.todolist.repository.LabelledTasksViewRepository;
import org.spine3.examples.todolist.repository.MyListViewRepository;
import org.spine3.examples.todolist.repository.TaskDefinitionRepository;
import org.spine3.examples.todolist.repository.TaskLabelsRepository;
import org.spine3.server.BoundedContext;

/**
 * Serves for creation the {@link BoundedContext} instances.
 *
 * @author Illia Shepilov
 */
public class TodoListBoundedContext {

    /** The name of the Bounded Context. */
    private static final String NAME = "TodoListBoundedContext";

    /**
     * Obtains the reference to the singleton {@link BoundedContext}.
     */
    public static BoundedContext getInstance() {
        return Singleton.INSTANCE.value;
    }

    /**
     * Creates and returns the {@link BoundedContext} instance.
     *
     * <p>Serves only for test needs.
     *
     * @return the {@link BoundedContext} instance
     */
    @VisibleForTesting
    public static BoundedContext createTestInstance() {
        final BoundedContext result = create();
        return result;
    }

    private TodoListBoundedContext() {
        // Disable instantiation from outside.
    }

    /**
     * Creates a new instance of the Bounded Context.
     */
    private static BoundedContext create() {
        final BoundedContext boundedContext = createBoundedContext();

        boundedContext.register(new TaskDefinitionRepository(boundedContext));
        boundedContext.register(new TaskLabelsRepository(boundedContext));
        boundedContext.register(new LabelAggregateRepository(boundedContext));
        boundedContext.register(new MyListViewRepository(boundedContext));
        boundedContext.register(new LabelledTasksViewRepository(boundedContext));
        boundedContext.register(new DraftTasksViewRepository(boundedContext));

        TodoListEventEnricher.newBuilder()
                             .setEventBus(boundedContext.getEventBus())
                             .setLabelRepository(new LabelAggregateRepository(boundedContext))
                             .setTaskDefinitionRepository(new TaskDefinitionRepository(boundedContext))
                             .setTaskLabelsRepository(new TaskLabelsRepository(boundedContext))
                             .build()
                             .addEnrichmentFields();
        return boundedContext;
    }

    private static BoundedContext createBoundedContext() {
        final BoundedContext result = BoundedContext.newBuilder()
                                                    .setName(NAME)
                                                    .build();
        return result;
    }

    /** The holder for the singleton reference. */
    private enum Singleton {
        INSTANCE;

        @SuppressWarnings("NonSerializableFieldInSerializableClass")
        private final BoundedContext value = create();
    }
}

@@ -2649,32 +2649,60 @@
     
-boundedContext.register(
+final TaskDefinitionRepository taskDefinitionRepo = 
 new 
@@ -2733,33 +2733,32 @@
 (boundedContext)
-)
 ;%0A        bounde
@@ -2755,32 +2755,158 @@
     
-boundedContext.register(
+final LabelAggregateRepository labelAggregateRepo = new LabelAggregateRepository(boundedContext);%0A        final TaskLabelsRepository taskLabelsRepo = 
 new 
@@ -2933,33 +2933,32 @@
 (boundedContext)
-)
 ;%0A        bounde
@@ -2955,50 +2955,173 @@
     
-boundedContext.register(new LabelAggregate
+final MyListViewRepository myListViewRepo = new MyListViewRepository(boundedContext);%0A        final LabelledTasksViewRepository tasksViewRepo = new LabelledTasksView
 Repo
@@ -3134,33 +3134,32 @@
 (boundedContext)
-)
 ;%0A        bounde
@@ -3156,42 +3156,74 @@
     
-boundedContext.register(new MyList
+final DraftTasksViewRepository draftTasksViewRepo = new DraftTasks
 View
@@ -3240,35 +3240,35 @@
 (boundedContext)
-)
 ;%0A
+%0A
         boundedC
@@ -3287,55 +3287,177 @@
 ter(
-new LabelledTasksViewRepository(boundedContext)
+taskDefinitionRepo);%0A        boundedContext.register(taskLabelsRepo);%0A        boundedContext.register(labelAggregateRepo);%0A        boundedContext.register(myListViewRepo
 );%0A 
@@ -3487,26 +3487,17 @@
 egister(
-new DraftT
+t
 asksView
@@ -3492,39 +3492,43 @@
 er(tasksViewRepo
-sitory(
+);%0A        
 boundedContext))
@@ -3525,17 +3525,44 @@
 dContext
-)
+.register(draftTasksViewRepo
 );%0A%0A    
@@ -3721,21 +3721,17 @@
 ository(
-new L
+l
 abelAggr
@@ -3739,38 +3739,16 @@
 gateRepo
-sitory(boundedContext)
 )%0A      
@@ -3799,21 +3799,17 @@
 ository(
-new T
+t
 askDefin
@@ -3817,38 +3817,16 @@
 tionRepo
-sitory(boundedContext)
 )%0A      
@@ -3873,21 +3873,17 @@
 ository(
-new T
+t
 askLabel
@@ -3887,38 +3887,16 @@
 belsRepo
-sitory(boundedContext)
 )%0A      

Declare local variables instead of inline declaration.