/*
 * Copyright 2018 Google LLC
 *
 * 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
 *
 *     https://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 com.google.android.gnd.ui.observationdetails;

import static com.google.android.gnd.rx.RxAutoDispose.autoDisposable;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gnd.MainActivity;
import com.google.android.gnd.R;
import com.google.android.gnd.databinding.ObservationDetailsFieldBinding;
import com.google.android.gnd.databinding.ObservationDetailsFragBinding;
import com.google.android.gnd.databinding.PhotoFieldBinding;
import com.google.android.gnd.model.form.Element;
import com.google.android.gnd.model.form.Field;
import com.google.android.gnd.model.form.Field.Type;
import com.google.android.gnd.model.observation.Observation;
import com.google.android.gnd.model.observation.Response;
import com.google.android.gnd.rx.Loadable;
import com.google.android.gnd.ui.common.AbstractFragment;
import com.google.android.gnd.ui.common.EphemeralPopups;
import com.google.android.gnd.ui.common.Navigator;
import com.google.android.gnd.ui.editobservation.PhotoFieldViewModel;
import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;
import timber.log.Timber;

@AndroidEntryPoint
public class ObservationDetailsFragment extends AbstractFragment {

  @Inject Navigator navigator;

  private ObservationDetailsViewModel viewModel;
  private ObservationDetailsFragBinding binding;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ObservationDetailsFragmentArgs args = getObservationDetailFragmentArgs();
    viewModel = getViewModel(ObservationDetailsViewModel.class);
    viewModel.observations.observe(this, this::onUpdate);
    viewModel.loadObservationDetails(args);
  }

  @Override
  public View onCreateView(
      @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    binding = ObservationDetailsFragBinding.inflate(inflater, container, false);
    binding.setViewModel(viewModel);
    binding.setLifecycleOwner(this);
    return binding.getRoot();
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((MainActivity) getActivity()).setActionBar(binding.observationDetailsToolbar, false);
  }

  @Override
  public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.observation_details_menu, menu);
  }

  @Override
  public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);
  }

  private void onUpdate(Loadable<Observation> observation) {
    switch (observation.getState()) {
      case LOADED:
        observation.value().ifPresent(this::showObservation);
        break;
      case NOT_FOUND:
      case ERROR:
        // TODO: Replace w/error view?
        Timber.e("Failed to load observation");
        EphemeralPopups.showError(getContext());
        break;
      default:
        Timber.e("Unhandled state: %s", observation.getState());
        break;
    }
  }

  private void showObservation(Observation observation) {
    binding.observationDetailsLayout.removeAllViews();
    for (Element element : observation.getForm().getElements()) {
      if (element.getType() == Element.Type.FIELD) {
        addField(element.getField(), observation);
      }
    }
  }

  private void addField(Field field, Observation observation) {
    ObservationDetailsFieldBinding fieldBinding =
        ObservationDetailsFieldBinding.inflate(getLayoutInflater());
    fieldBinding.setField(field);
    fieldBinding.setLifecycleOwner(this);
    binding.observationDetailsLayout.addView(fieldBinding.getRoot());

    observation
        .getResponses()
        .getResponse(field.getId())
        .ifPresent(
            response -> {
              if (field.getType() == Type.PHOTO) {
                addPhotoField((ViewGroup) fieldBinding.getRoot(), field, response);
              } else {
                fieldBinding.fieldValue.setText(response.getDetailsText(field));
              }
            });
  }

  private void addPhotoField(ViewGroup container, Field field, Response response) {
    PhotoFieldBinding photoFieldBinding = PhotoFieldBinding.inflate(getLayoutInflater());
    PhotoFieldViewModel photoFieldViewModel = viewModelFactory.create(PhotoFieldViewModel.class);
    photoFieldBinding.setLifecycleOwner(this);
    photoFieldBinding.setViewModel(photoFieldViewModel);
    photoFieldViewModel.updateField(response, field);
    container.addView(photoFieldBinding.getRoot());
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    ObservationDetailsFragmentArgs args = getObservationDetailFragmentArgs();
    String projectId = args.getProjectId();
    String featureId = args.getFeatureId();
    String observationId = args.getObservationId();

    switch (item.getItemId()) {
      case R.id.edit_observation_menu_item:
        // This is required to prevent menu from reappearing on back.
        getActivity().closeOptionsMenu();
        navigator.editObservation(projectId, featureId, observationId);
        return true;
      case R.id.delete_observation_menu_item:
        viewModel
            .deleteCurrentObservation(projectId, featureId, observationId)
            .doOnError(Timber::e)
            .as(autoDisposable(this))
            .subscribe(
                () -> {
                  Timber.d("Deleted successfully");
                  navigator.navigateUp();
                });
        return true;
      default:
        return false;
    }
  }

  private ObservationDetailsFragmentArgs getObservationDetailFragmentArgs() {
    return ObservationDetailsFragmentArgs.fromBundle(getArguments());
  }
}

@@ -6188,42 +6188,8 @@
 Id)%0A
-            .doOnError(Timber::e)%0A
     
@@ -6249,102 +6249,13 @@
 ibe(
-%0A                () -%3E %7B%0A                  Timber.d(%22Deleted successfully%22);%0A                 
+() -%3E
  nav
@@ -6277,27 +6277,8 @@
 Up()
-;%0A                %7D
 );%0A 

Remove debug messages