// Path: sample-android/src/main/java/com/example/sample_android/action/Action.java
// public interface Action {
// }
// 
// Path: sample-android/src/main/java/com/example/sample_android/state/TodoList.java
// @AutoValue
// public abstract class TodoList {
// 
//     public static TodoList initial() {
//         return new AutoValue_TodoList(true, Collections.<TodoItem>emptyList());
//     }
// 
//     public static TodoList create(boolean loading, List<TodoItem> items) {
//         return new AutoValue_TodoList(loading, Collections.unmodifiableList(items));
//     }
//     
//     public abstract boolean loading();
// 
//     public abstract List<TodoItem> items();
// }
// 
// Path: redux-replay/src/main/java/me/tatarka/redux/ReplayMiddleware.java
// public class ReplayMiddleware<S, A, R> implements Middleware<A, R> {
// 
//     private final S initialState;
//     private final Store<S> store;
//     private final Dispatcher<A, A> dispatcher;
//     private final ArrayList<A> actions = new ArrayList<>();
//     private final Set<Integer> disabled = new HashSet<>();
//     private boolean runningActions;
// 
//     public ReplayMiddleware(Store<S> store, Reducer<A, S> reducer) {
//         this.initialState = store.getState();
//         this.store = store;
//         this.dispatcher = Dispatcher.forStore(store, reducer);
//     }
// 
//     @Override
//     public R dispatch(Next<A, R> next, A action) {
//         if (!runningActions) {
//             actions.add(action);
//         }
//         return next.next(action);
//     }
// 
//     public List<A> actions() {
//         return Collections.unmodifiableList(actions);
//     }
// 
//     public boolean isDisabled(int index) {
//         return disabled.contains(index);
//     }
// 
//     public void disable(int index) {
//         disabled.add(index);
//         rerunActions();
//     }
// 
//     public void enable(int index) {
//         disabled.remove(index);
//         rerunActions();
//     }
// 
//     public void replace(int index, A newAction) {
//         actions.set(index, newAction);
//         rerunActions();
//     }
// 
//     public void remove(int index) {
//         actions.remove(index);
//         disabled.remove(index);
//         rerunActions();
//     }
// 
//     private void rerunActions() {
//         store.setState(initialState);
//         runningActions = true;
//         for (int i = 0; i < actions.size(); i++) {
//             if (!disabled.contains(i)) {
//                 A action = actions.get(i);
//                 dispatcher.dispatch(action);
//             }
//         }
//         runningActions = false;
//     }
// }


import android.app.Dialog;
import androidx.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.example.sample_android.action.Action;
import com.example.sample_android.state.TodoList;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import me.tatarka.redux.ReplayMiddleware;
        final LinearLayout layout = new LinearLayout(getContext());
        int padding = getResources().getDimensionPixelOffset(R.dimen.padding);
        layout.setPadding(padding, padding, padding, padding);
        layout.setOrientation(LinearLayout.VERTICAL);
        for (Field field : action.getClass().getDeclaredFields()) {
            if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isTransient(field.getModifiers())) {
                layout.addView(createInput(getContext(), field, action), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        }
        return new AlertDialog.Builder(getContext(), getTheme())
                .setTitle("Edit " + action.getClass().getSimpleName())
                .setView(layout)
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            Action newAction = unsafe.newInstance(action.getClass());
                            for (int i = 0; i < layout.getChildCount(); i++) {
                                TextInputLayout input = (TextInputLayout) layout.getChildAt(i);
                                EditText editText = input.getEditText();
                                Field field = (Field) input.getTag();
                                field.set(newAction, toType(field, editText.getText().toString()));
                            }
                            middleware.replace(index, newAction);
                        } catch (Exception e) {
                            Log.e(TAG, e.getMessage(), e);
                            Toast.makeText(getContext(), "Error changing action " + action.getClass().getSimpleName(), Toast.LENGTH_SHORT).show();
                        }
                    }
                })
// Path: sample-android/src/main/java/com/example/sample_android/action/Action.java
// public interface Action {
// }
// 
// Path: sample-android/src/main/java/com/example/sample_android/state/TodoList.java
// @AutoValue
// public abstract class TodoList {
// 
//     public static TodoList initial() {
//         return new AutoValue_TodoList(true, Collections.<TodoItem>emptyList());
//     }
// 
//     public static TodoList create(boolean loading, List<TodoItem> items) {
//         return new AutoValue_TodoList(loading, Collections.unmodifiableList(items));
//     }
//     
//     public abstract boolean loading();
// 
//     public abstract List<TodoItem> items();
// }
// 
// Path: redux-replay/src/main/java/me/tatarka/redux/ReplayMiddleware.java
// public class ReplayMiddleware<S, A, R> implements Middleware<A, R> {
// 
//     private final S initialState;
//     private final Store<S> store;
//     private final Dispatcher<A, A> dispatcher;
//     private final ArrayList<A> actions = new ArrayList<>();
//     private final Set<Integer> disabled = new HashSet<>();
//     private boolean runningActions;
// 
//     public ReplayMiddleware(Store<S> store, Reducer<A, S> reducer) {
//         this.initialState = store.getState();
//         this.store = store;
//         this.dispatcher = Dispatcher.forStore(store, reducer);
//     }
// 
//     @Override
//     public R dispatch(Next<A, R> next, A action) {
//         if (!runningActions) {
//             actions.add(action);
//         }
//         return next.next(action);
//     }
// 
//     public List<A> actions() {
//         return Collections.unmodifiableList(actions);
//     }
// 
//     public boolean isDisabled(int index) {
//         return disabled.contains(index);
//     }
// 
//     public void disable(int index) {
//         disabled.add(index);
//         rerunActions();
//     }
// 
//     public void enable(int index) {
//         disabled.remove(index);
//         rerunActions();
//     }
// 
//     public void replace(int index, A newAction) {
//         actions.set(index, newAction);
//         rerunActions();
//     }
// 
//     public void remove(int index) {
//         actions.remove(index);
//         disabled.remove(index);
//         rerunActions();
//     }
// 
//     private void rerunActions() {
//         store.setState(initialState);
//         runningActions = true;
//         for (int i = 0; i < actions.size(); i++) {
//             if (!disabled.contains(i)) {
//                 A action = actions.get(i);
//                 dispatcher.dispatch(action);
//             }
//         }
//         runningActions = false;
//     }
// }


// Path: sample-android/src/main/java/com/example/sample_android/EditActionDialogFragment.java
import android.app.Dialog;
import androidx.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.example.sample_android.action.Action;
import com.example.sample_android.state.TodoList;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import me.tatarka.redux.ReplayMiddleware;

        final LinearLayout layout = new LinearLayout(getContext());
        int padding = getResources().getDimensionPixelOffset(R.dimen.padding);
        layout.setPadding(padding, padding, padding, padding);
        layout.setOrientation(LinearLayout.VERTICAL);
        for (Field field : action.getClass().getDeclaredFields()) {
            if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isTransient(field.getModifiers())) {
                layout.addView(createInput(getContext(), field, action), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        }
        return new AlertDialog.Builder(getContext(), getTheme())
                .setTitle("Edit " + action.getClass().getSimpleName())
                .setView(layout)
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            Action newAction = unsafe.newInstance(action.getClass());
                            for (int i = 0; i < layout.getChildCount(); i++) {
                                TextInputLayout input = (TextInputLayout) layout.getChildAt(i);
                                EditText editText = input.getEditText();
                                Field field = (Field) input.getTag();
                                field.set(newAction, toType(field, editText.getText().toString()));
                            }
                            middleware.replace(index, newAction);
                        } catch (Exception e) {
                            Log.e(TAG, e.getMessage(), e);
                            Toast.makeText(getContext(), "Error changing action " + action.getClass().getSimpleName(), Toast.LENGTH_SHORT).show();
                        }
                    }
                })
                .setNegativeButton("Delete", new DialogInterface.OnClickListener() {