/*
 * 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 io.spine.examples.todolist.mode.action;

import io.spine.examples.todolist.TaskId;
import io.spine.examples.todolist.c.commands.CreateBasicTask;
import io.spine.examples.todolist.c.commands.CreateBasicTaskVBuilder;
import io.spine.examples.todolist.mode.Mode;
import io.spine.validate.ValidationException;

import java.util.Optional;

import static io.spine.base.Identifier.newUuid;
import static io.spine.examples.todolist.UserIO.askUser;
import static io.spine.examples.todolist.mode.action.ValidationExceptionFormatter.format;
import static io.spine.util.Exceptions.illegalStateWithCauseOf;

/**
 * @author Dmytro Grankin
 */
public class QuickTaskCreation extends Mode {

    private static final String SET_DESCRIPTION_MESSAGE = "Please enter the task description";

    private final CreateBasicTaskVBuilder builder = CreateBasicTaskVBuilder.newBuilder();

    @Override
    public void start() {
        final TaskId taskId = newTaskId(newUuid());
        set(taskId);

        inputDescription();

        execute();
    }

    private void set(TaskId taskId) {
        try {
            builder.setId(taskId);
        } catch (ValidationException e) {
            throw illegalStateWithCauseOf(e);
        }
    }

    private void inputDescription() {
        String description = askUser(SET_DESCRIPTION_MESSAGE);
        Optional<String> errMsg = trySet(description);
        while (errMsg.isPresent()) {
            description = askUser(errMsg.get());
            errMsg = trySet(description);
        }
    }

    private Optional<String> trySet(String description) {
        try {
            builder.setDescription(description);
            return Optional.empty();
        } catch (ValidationException e) {
            final String errMsg = format(e);
            return Optional.of(errMsg);
        }
    }

    private void execute() {
        try {
            final CreateBasicTask createTask = builder.build();
            getClient().create(createTask);
        } catch (ValidationException e) {
            throw illegalStateWithCauseOf(e);
        }
    }

    private static TaskId newTaskId(String taskIdValue) {
        final TaskId result = TaskId.newBuilder()
                                    .setValue(taskIdValue)
                                    .build();
        return result;
    }
}

@@ -1965,17 +1965,8 @@
 kId(
-newUuid()
 );%0A 
@@ -1972,19 +1972,29 @@
         
+builder.
 set
+Id
 (taskId)
@@ -2025,222 +2025,58 @@
 ion(
-);%0A%0A        execute();%0A    %7D%0A%0A    private void set(TaskId taskId) %7B%0A        try %7B%0A            builder.setId(taskId);%0A        %7D catch (ValidationException e) %7B%0A            throw illegalStateWithCauseOf(e);%0A        %7D
+SET_DESCRIPTION_MESSAGE);%0A%0A        buildAndPost();
 %0A   
@@ -2113,16 +2113,30 @@
 ription(
+String message
 ) %7B%0A    
@@ -2139,16 +2139,22 @@
         
+final 
 String d
@@ -2174,39 +2174,23 @@
 askUser(
-SET_DESCRIPTION_MESSAGE
+message
 );%0A     
@@ -2192,16 +2192,22 @@
         
+final 
 Optional
@@ -2235,137 +2235,89 @@
 Set(
-description);%0A        while (errMsg.isPresent()) %7B%0A            description = askUser(errMsg.get());%0A            errMsg = trySet(d
+() -%3E builder.setDescription(description));%0A        errMsg.ifPresent(this::inputD
 escr
@@ -2325,26 +2325,16 @@
 ption);%0A
-        %7D%0A
     %7D%0A%0A 
@@ -2348,114 +2348,105 @@
 ate 
-Optional%3CString%3E trySet(String description) %7B%0A        try %7B%0A            builder.setDescription(description
+void buildAndPost() %7B%0A        try %7B%0A            final CreateBasicTask createTask = builder.build(
 );%0A 
@@ -2460,30 +2460,37 @@
     
-return Optional.empty(
+getClient().create(createTask
 );%0A 
@@ -2546,201 +2546,147 @@
     
-final String errMsg = format(e);%0A            return Optional.of(errMsg);%0A        %7D%0A    %7D%0A%0A    private void execute() %7B%0A        try %7B%0A            final CreateBasicTask createTask = builder.build
+throw illegalStateWithCauseOf(e);%0A        %7D%0A    %7D%0A%0A    private static Optional%3CString%3E trySet(Runnable r) %7B%0A        try %7B%0A            r.run
 ();%0A
@@ -2701,37 +2701,30 @@
     
-getClient().create(createTask
+return Optional.empty(
 );%0A 
@@ -2780,39 +2780,78 @@
     
-throw illegalStateWithCauseOf(e
+final String errMsg = format(e);%0A            return Optional.of(errMsg
 );%0A 
@@ -2906,26 +2906,8 @@
 kId(
-String taskIdValue
 ) %7B%0A
@@ -3006,19 +3006,17 @@
 lue(
-taskIdValue
+newUuid()
 )%0A  

Improve `QuickTaskCreation` structure