content: /*
   * Copyright 2016, The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package <%= appPackage %>.addedittask;
  
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  
  import <%= appPackage %>.data.Task;
  import <%= appPackage %>.data.source.TasksDataSource;
  import <%= appPackage %>.data.source.TasksRepository;
  
  import javax.inject.Inject;
  
  /**
   * Listens to user actions from the UI ({@link AddEditTaskFragment}), retrieves the data and
   * updates
   * the UI as required.
   * <p />
   * By marking the constructor with {@code @Inject}, Dagger injects the dependencies required to
   * create an instance of the AddEditTaskPresenter (if it fails, it emits a compiler error). It uses
   * {@link AddEditTaskPresenterModule} to do so.
   * <p/>
   * Dagger generated code doesn't require public access to the constructor or class, and
   * therefore, to ensure the developer doesn't instantiate the class manually bypassing Dagger,
   * it's good practice minimise the visibility of the class/constructor as much as possible.
   */
  final class AddEditTaskPresenter implements AddEditTaskContract.Presenter,
          TasksDataSource.GetTaskCallback {
  
      @NonNull
      private final TasksDataSource mTasksRepository;
  
      @NonNull
      private final AddEditTaskContract.View mAddTaskView;
  
      @Nullable
      private String mTaskId;
  
      /**
       * Dagger strictly enforces that arguments not marked with {@code @Nullable} are not injected
       * with {@code @Nullable} values.
       */
      @Inject
      AddEditTaskPresenter(@Nullable String taskId, TasksRepository tasksRepository,
              AddEditTaskContract.View addTaskView) {
          mTaskId = taskId;
          mTasksRepository = tasksRepository;
          mAddTaskView = addTaskView;
      }
  
      /**
       * Method injection is used here to safely reference {@code this} after the object is created.
       * For more information, see Java Concurrency in Practice.
       */
      @Inject
      void setupListeners() {
          mAddTaskView.setPresenter(this);
      }
  
      @Override
      public void start() {
          if (!isNewTask()) {
              populateTask();
          }
      }
  
      @Override
      public void saveTask(String title, String description) {
          if (isNewTask()) {
              createTask(title, description);
          } else {
              updateTask(title, description);
          }
      }
  
      @Override
      public void populateTask() {
          if (isNewTask()) {
              throw new RuntimeException("populateTask() was called but task is new.");
          }
          mTasksRepository.getTask(mTaskId, this);
      }
  
      @Override
      public void onTaskLoaded(Task task) {
          // The view may not be able to handle UI updates anymore
          if (mAddTaskView.isActive()) {
              mAddTaskView.setTitle(task.getTitle());
              mAddTaskView.setDescription(task.getDescription());
          }
      }
  
      @Override
      public void onDataNotAvailable() {
          // The view may not be able to handle UI updates anymore
          if (mAddTaskView.isActive()) {
              mAddTaskView.showEmptyTaskError();
          }
      }
  
      private boolean isNewTask() {
          return mTaskId == null;
      }
  
      private void createTask(String title, String description) {
          Task newTask = new Task(title, description);
          if (newTask.isEmpty()) {
              mAddTaskView.showEmptyTaskError();
          } else {
              mTasksRepository.saveTask(newTask);
              mAddTaskView.showTasksList();
          }
      }
  
      private void updateTask(String title, String description) {
          if (isNewTask()) {
              throw new RuntimeException("updateTask() was called but task is new.");
          }
          mTasksRepository.saveTask(new Task(title, description, mTaskId));
          mAddTaskView.showTasksList(); // After an edit, go back to the list.
      }
  }
  