// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.todos;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toolbar;

import com.firebase.client.ChildEventListener;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;

import io.v.todos.persistence.FirebasePersistence;

/**
 * TodoListActivity for Vanadium TODOs
 *
 * This activity shows a list of tasks.
 * - Tap on a Task in order to edit it.
 * - Swipe Left on a Task to delete it.
 * - Swipe Right in order to mark the Task as done.
 * - Select Edit from the menu to Edit the Todo List.
 * - Toggle Show Done in the menu to show/hide completed Tasks.
 *
 * @author alexfandrianto
 */
public class TodoListActivity extends Activity {
    private Firebase myFirebaseRef;

    private final static String SNACKOO_LISTS = "snackoo lists (Task)";
    private String snackooKey;
    private TodoList snackoo;
    private DataList<Task> snackoosList = new DataList<Task>();
    private boolean showDone = false; // TODO(alexfandrianto): Load from shared preferences...

    // This adapter handle mirrors the firebase list values and generates the corresponding todo
    // item View children for a list view.
    private TaskRecyclerAdapter adapter;
    private ValueEventListener snackooEventListener;
    private ChildEventListener snackoosEventListener;

    @Override
    protected void onDestroy() {
        myFirebaseRef.removeEventListener(snackooEventListener);
        myFirebaseRef.removeEventListener(snackoosEventListener);
        super.onDestroy();
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = getIntent();
        snackooKey = intent.getStringExtra(MainActivity.INTENT_SNACKOO_KEY);

        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setActionBar(toolbar);

        // Set up the todo list adapter
        final Activity self = this;
        adapter = new TaskRecyclerAdapter(snackoosList, new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String key = (String) view.getTag();

                initiateTaskEdit(key);
            }
        });

        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler);
        recyclerView.setAdapter(adapter);

        new ItemTouchHelper(new SwipeableTouchHelperCallback() {
            @Override
            public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) {
                if (direction == ItemTouchHelper.RIGHT) {
                    Log.d(SNACKOO_LISTS, "Gonna mark all tasks as done");
                    markAsDone((String)viewHolder.itemView.getTag());
                } else if (direction == ItemTouchHelper.LEFT) {
                    Log.d(SNACKOO_LISTS, "Gonna delete this todo list");
                    deleteTodoItem((String)viewHolder.itemView.getTag());
                }
            }
        }).attachToRecyclerView(recyclerView);

        // Prepare our Firebase Reference and the primary listener (SNACKOOS).
        FirebasePersistence.getDatabase(this);
        myFirebaseRef = new Firebase(MainActivity.FIREBASE_EXAMPLE_URL);
        setUpSnackoo();
        setUpSnackoos();
    }

    private Firebase firebaseListReference() {
        return myFirebaseRef.child(MainActivity.SNACKOOS).child(snackooKey);
    }

    private Firebase firebaseTasksReference() {
        return myFirebaseRef.child(SNACKOO_LISTS).child(snackooKey);
    }

    private void setUpSnackoo() {
        snackooEventListener = firebaseListReference().addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                snackoo = dataSnapshot.getValue(TodoList.class);
                if (snackoo == null) {
                    // The list has been deleted. Get the heck out of here!
                    finish();
                    return;
                }
                getActionBar().setTitle(snackoo.getName());
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });
    }

    // Set the visibility based on what the adapter thinks is the visible item count.
    private void setEmptyVisiblity() {
        View v = findViewById(R.id.empty);
        v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
    }

    // Any time a child of SNACKOOS is added/changed/removed, we mirror the changes locally.
    private void setUpSnackoos() {
        snackoosEventListener = firebaseTasksReference().addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String prevKey) {
                String fbKey = dataSnapshot.getKey();
                Task task = dataSnapshot.getValue(Task.class);
                task.setKey(fbKey);
                snackoosList.insertInOrder(task);
                adapter.notifyDataSetChanged();

                setEmptyVisiblity();
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String prevKey) {
                String fbKey = dataSnapshot.getKey();
                Task task = dataSnapshot.getValue(Task.class);
                task.setKey(fbKey);
                snackoosList.updateInOrder(task);
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                String fbKey = dataSnapshot.getKey();
                snackoosList.removeByKey(fbKey);
                adapter.notifyDataSetChanged();

                setEmptyVisiblity();
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String prevKey) {

            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });
    }

    public void addTodoItem(String todo) {
        // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
        firebaseTasksReference().push().setValue(new Task(todo));
    }

    public void updateTodoItem(String fbKey, String todo) {
        // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
        Task task = snackoosList.findByKey(fbKey).copy();
        task.setText(todo);
        firebaseTasksReference().child(fbKey).setValue(task);
    }
    public void markAsDone(String fbKey) {
        // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
        Task task = snackoosList.findByKey(fbKey).copy();
        task.setDone(!task.getDone());
        firebaseTasksReference().child(fbKey).setValue(task);
    }

    public void deleteTodoItem(String fbKey) {
        // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
        firebaseTasksReference().child(fbKey).removeValue();
    }

    public void addCallback(View view) {
        final EditText todoItem = new EditText(this);

        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("New Todo")
                .setView(todoItem)
                .setPositiveButton("Add", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        addTodoItem(todoItem.getText().toString());
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                }).show();
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }

    private void initiateTaskEdit(final String fbKey) {
        final EditText todoItem = new EditText(this);
        todoItem.setText(snackoosList.findByKey(fbKey).getText());

        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("Editing Task")
                .setView(todoItem)
                .setPositiveButton("Save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        updateTodoItem(fbKey, todoItem.getText().toString());
                    }
                })
                .setNeutralButton("Delete", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        deleteTodoItem(fbKey);
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                }).show();
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }

    private void initiateTodoListEdit() {
        final EditText todoItem = new EditText(this);
        todoItem.setText(snackoo.getName());

        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("Editing Todo List")
                .setView(todoItem)
                .setPositiveButton("Save", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        updateTodoList(todoItem.getText().toString());
                    }
                })
                .setNeutralButton("Delete", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        deleteTodoList();
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                }).show();
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }


    public void updateTodoList(String todo) {
        firebaseListReference().setValue(new TodoList(todo));
    }

    public void deleteTodoList() {
        firebaseListReference().removeValue();
    }


    // The following methods are boilerplate for handling the Menu in the top right corner.
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_task, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        switch (id) {
            case R.id.show_done:
                if(item.isChecked()){
                    item.setChecked(false);
                    adapter.setShowDone(false);
                }else{
                    item.setChecked(true);
                    adapter.setShowDone(true);
                }
                adapter.notifyDataSetChanged();

                // TODO(alexfandrianto): You may wish to save this data into SharedPreferences.
                // You may also wish to save this to a different part of the space which is synced
                // across your devices.

                return true;
            case R.id.action_settings:
                return true;
            case R.id.action_edit:
                initiateTodoListEdit();
                return true;
            case R.id.action_share:
                return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
