package kz.arta.synergy.workflow.mobile.android.documents.route.activities;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import kz.arta.synergy.workflow.mobile.android.R;
import kz.arta.synergy.workflow.mobile.android.common.ActivityConst;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.utils.UserSerializable;
import kz.arta.synergy.workflow.mobile.android.documents.route.RouteUtils;
import kz.arta.synergy.workflow.mobile.android.documents.route.RoutesConst;
import kz.arta.synergy.workflow.mobile.android.documents.route.models.Route;
import kz.arta.synergy.workflow.mobile.android.documents.route.models.RouteItem;
import kz.arta.synergy.workflow.mobile.android.documents.route.models.RouteItemUser;

/**
 * Created by neox on 24.07.15.
 * Активити с подробным описанием маршрута
 */
public class RouteItemsActivity extends Activity {

    /**
     * StartActivityForResult
     */
    public static final int ADD_ITEM = 1;

    /**
     * Данные авторизированного пользователя
     */
    private Person person;

    /**
     * Текущее активити
     */
    private Activity activity;

    /**
     * Маршрут, с которым работаем в данный момент
     */
    private Route route;

    /**
     * Тип события
     *
     * @see RoutesConst#BEFORE
     * @see RoutesConst#ACTION
     * @see RoutesConst#AFTER
     */
    private int routeType;

    /**
     * Номер этапа в списке (используется при редактировании)
     */
    private int currentItemPosition;

    /**
     * Номер подэтапа в этапах (используется при редактировании)
     */
    private int currentItemUserPosition;

    /**
     * Коды этапов
     */
    private HashSet<String> codes;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.route_items_acitvity);

        activity = this;

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.hide();
        }

        Intent intent = getIntent();
        person = (Person) intent.getSerializableExtra(ActivityConst.PERSON);
        route = (Route) intent.getSerializableExtra(RoutesConst.ROUTE);
        routeType = intent.getIntExtra(RoutesConst.ROUTE_TYPE, 0);
        codes = (HashSet<String>) intent.getSerializableExtra(RoutesConst.CODES);

        TextView activityName = (TextView) findViewById(R.id.route_items_activity_action_bar_title);
        switch (routeType) {
            case RoutesConst.BEFORE: {
                activityName.setText(getResources().getString(R.string.before_steps));
            }
            break;
            case RoutesConst.ACTION: {
                activityName.setText(getResources().getString(R.string.actions));
            }
            break;
            case RoutesConst.AFTER: {
                activityName.setText(getResources().getString(R.string.after_steps));
            }
            break;
        }

        init();
        initButtons();
    }

    /**
     * Инициализация кнопок
     */
    private void initButtons() {
        // кнопка "Добавить этап"
        Button addItem = (Button) findViewById(R.id.route_items_activity_button_add);
        addItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addItemActivity();
            }
        });
        // кнопка "Готово" - закрывает экран и отправляет обновленню информацию о маршрутах в предыдущее активити
        Button finish = (Button) findViewById(R.id.route_items_activity_button_save);
        finish.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra(RoutesConst.ROUTE, route);
                setResult(Activity.RESULT_OK, intent);
                finish();
                Toast.makeText(activity, getString(R.string.data_saved), Toast.LENGTH_LONG).show();
            }
        });
        // для "действий" кнопка "добавить этап" не нужна
        if (routeType == RoutesConst.ACTION) {
            addItem.setVisibility(View.GONE);
        }
    }

    /**
     * Инициализация
     */
    private void init() {
        LayoutInflater inflater = activity.getLayoutInflater();
        LinearLayout layout = (LinearLayout) findViewById(R.id.route_items_activity_layout);
        layout.removeAllViews();
        int position = 0;
        for (RouteItem item : route.getItems()) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.setMargins(0, (int) (getResources().getDimension(R.dimen.activity_components_margin)), 0, 0);
            LinearLayout routeItem = new LinearLayout(activity);
            routeItem.setOrientation(LinearLayout.VERTICAL);
            routeItem.setLayoutParams(params);
            routeItem.setBackgroundResource(R.drawable.default_background_containers);
            int positionUserItem = 0;
            for (RouteItemUser user : item.getUsers()) {
                final View view = RouteUtils.getItem(inflater, user, routeItem, activity, person);
                assert view != null;
                view.setId(position);
                view.setTag(positionUserItem);
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        currentItemPosition = v.getId();
                        currentItemUserPosition = Integer.parseInt(v.getTag().toString());
                        // для "действий" событие недоступно
                        if (routeType == RoutesConst.ACTION) {
                            return;
                        }
                        editItemActivity();
                    }
                });
                view.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        currentItemPosition = v.getId();
                        currentItemUserPosition = Integer.parseInt(v.getTag().toString());
                        // для "действий" событие недоступно
                        if (routeType == RoutesConst.ACTION) {
                            return false;
                        }
                        showEditItemDialog();
                        return true;
                    }
                });
                routeItem.addView(view);
                positionUserItem++;
            }
            RouteUtils.removeLastSplit(routeItem);
            layout.addView(routeItem);
            position++;
        }
    }

    /**
     * Метод вызываетя при долгом нажатии на плашку (открытие диалога)
     */
    private void showEditItemDialog() {
        String[] items = {
                getString(R.string.add_route_item_user),
                getString(R.string.move_route_item_user_up),
                getString(R.string.move_route_item_user_down),
                getString(R.string.delete_route_item_user),
                getString(R.string.delete_route_item)
        };
        AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
        dialog.setTitle(getString(R.string.edit_route_item));
        dialog.setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int pos) {
                switch (pos) {
                    case 0: {
                        Intent intent = new Intent(activity, AddRouteItemActivity.class);
                        intent.putExtra(ActivityConst.PERSON, person);
                        intent.putExtra(RoutesConst.ROUTE_ITEM_USER, route.getItems().get(currentItemPosition).getUsers().get(currentItemUserPosition));
                        intent.putExtra(RoutesConst.ROUTE_ITEM_NUMBER, currentItemPosition + 1);
                        intent.putExtra(RoutesConst.CODE, route.getItems().get(currentItemPosition).getCode());
                        intent.putExtra(RoutesConst.CODES, codes);
                        intent.putExtra(RoutesConst.ADD_PARALLEL, true);
                        startActivityForResult(intent, ADD_ITEM);
                        break;
                    }
                    case 1: {
                        moveUp();
                        break;
                    }
                    case 2: {
                        moveDown();
                        break;
                    }
                    case 3: {
                        removeItemUser();
                        break;
                    }
                    case 4: {
                        removeItem();
                        break;
                    }
                }
            }
        });
        dialog.setCancelable(true);
        dialog.show();
    }

    /**
     * Метод вызывается для редактирования этапа маршрута (открытие нового активити)
     */
    private void editItemActivity() {
        Intent intent = new Intent(activity, AddRouteItemActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(RoutesConst.ROUTE_ITEM_USER, route.getItems().get(currentItemPosition).getUsers().get(currentItemUserPosition));
        intent.putExtra(RoutesConst.ROUTE_ITEM_NUMBER, currentItemPosition + 1);
        intent.putExtra(RoutesConst.CODE, route.getItems().get(currentItemPosition).getCode());
        intent.putExtra(RoutesConst.CODES, codes);
        startActivityForResult(intent, ADD_ITEM);
    }

    /**
     * Метод вызывается для добавления нового этапа маршрута (открытие нового активити)
     */
    private void addItemActivity() {
        Intent intent = new Intent(activity, AddRouteItemActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(RoutesConst.ROUTE_ITEM_NUMBER, route.getItems().size() + 1);
        intent.putExtra(RoutesConst.CODES, codes);
        startActivityForResult(intent, ADD_ITEM);
    }

    /**
     * Перемещение этапа вверх
     */
    private void moveUp() {
        // нельзя перемещать вверх первый пункт в списке
        if (currentItemPosition == 0) {
            return;
        }
        Collections.swap(route.getItems(), currentItemPosition, currentItemPosition - 1);
        init();
    }

    /**
     * Перемещение этапа вниз
     */
    private void moveDown() {
        // нельзя перемещать вниз второй пункт в списке
        if (currentItemPosition == route.getItems().size() - 1) {
            return;
        }
        Collections.swap(route.getItems(), currentItemPosition, currentItemPosition + 1);
        init();
    }

    /**
     * Удаление текущего подэтапа
     */
    private void removeItemUser() {
        AlertDialog.Builder ad = new AlertDialog.Builder(activity);
        ad.setTitle(getString(R.string.remove_route_item));
        ad.setMessage(getString(R.string.remove_route_item_question));
        ad.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int arg1) {
                route.getItems().get(currentItemPosition).getUsers().remove(currentItemUserPosition);
                init();
            }
        });
        ad.setNegativeButton(getString(R.string.no), null);
        ad.setCancelable(true);
        ad.show();
    }

    /**
     * Удаление этапа
     */
    private void removeItem() {
        AlertDialog.Builder ad = new AlertDialog.Builder(activity);
        ad.setTitle(getString(R.string.remove_route_item));
        ad.setMessage(getString(R.string.remove_route_item_question));
        ad.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int arg1) {
                route.getItems().remove(currentItemPosition);
                init();
            }
        });
        ad.setNegativeButton(getString(R.string.no), null);
        ad.setCancelable(true);
        ad.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_CANCELED) {
            return;
        }
        if (requestCode == ADD_ITEM) {
            // редактируется ли пункт, либо добавляется новый
            boolean edit = data.getBooleanExtra(ActivityConst.EDIT, false);
            // добавляется ли параллельный
            boolean parallel = data.getBooleanExtra(RoutesConst.ADD_PARALLEL, false);
            // добавленные ответственные
            UserSerializable users = (UserSerializable) data.getSerializableExtra(ActivityConst.SELECTED);
            // этап маршрута
            RouteItemUser item = (RouteItemUser) data.getSerializableExtra(RoutesConst.ROUTE_ITEM_USER);
            // код
            String code = data.getStringExtra(RoutesConst.CODE);
            // если добавляется новый пункт
            if (!edit) {
                List<RouteItemUser> routeItemUsers = new ArrayList<>();
                RouteItem routeItem = new RouteItem();
                routeItem.setUsers(routeItemUsers);
                if (code != null) {
                    codes.add(code);
                    routeItem.setCode(code);
                } else {
                    routeItem.setCode("");
                }
                // если нет ответственных - добавляем новый этап
                if (users == null || users.getUsersID() == null || users.getUsersID().isEmpty()) {
                    routeItemUsers.add(item);
                    route.getItems().add(routeItem);
                } else {
                    // если ответственные есть - пробегаемся по каждому и добавляем этап
                    // количество новых этапов равно количеству выбранных ответственных
                    for (int i = 0; i < users.getUsersID().size(); i++) {
                        RouteItemUser routeItemUser = getRouteItemUser(item);
                        routeItemUser.setUserID(users.getUsersID().get(i));
                        routeItemUser.setUserName(users.getNames().get(i));
                        routeItemUsers.add(routeItemUser);
                    }
                    route.getItems().add(routeItem);
                }
            } else {
                if (code != null) {
                    codes.remove(route.getItems().get(currentItemPosition).getCode());
                    codes.add(code);
                    route.getItems().get(currentItemPosition).setCode(code);
                } else {
                    route.getItems().get(currentItemPosition).setCode("");
                }
                // если нет ответственных - заменяем редактируемый этап
                if (users == null || users.getUsersID() == null || users.getUsersID().isEmpty()) {
                    if (parallel) {
                        route.getItems().get(currentItemPosition).getUsers().add(item);
                    } else {
                        route.getItems().get(currentItemPosition).getUsers().set(currentItemUserPosition, item);
                    }
                } else {
                    // если ответственный один - заменяем только этот этап
                    if (users.getUsersID().size() == 1) {
                        RouteItemUser routeItemUser = getRouteItemUser(item);
                        routeItemUser.setUserID(users.getUsersID().get(0));
                        routeItemUser.setUserName(users.getNames().get(0));
                        if (parallel) {
                            route.getItems().get(currentItemPosition).getUsers().add(routeItemUser);
                        } else {
                            route.getItems().get(currentItemPosition).getUsers().set(currentItemUserPosition, routeItemUser);
                        }
                    } else {
                        // если ответственных несколько - удаляем старый этап, и добавляем новые
                        for (int i = 0; i < users.getUsersID().size(); i++) {
                            RouteItemUser routeItemUser = getRouteItemUser(item);
                            routeItemUser.setUserID(users.getUsersID().get(i));
                            routeItemUser.setUserName(users.getNames().get(i));
                            route.getItems().get(currentItemPosition).getUsers().add(currentItemUserPosition + i + 1, routeItemUser);
                        }
                        if (!parallel) {
                            route.getItems().get(currentItemPosition).getUsers().remove(currentItemUserPosition);
                        }
                    }
                }
            }
            init();
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Метод возвращает этап маршрута
     *
     * @param item этап
     * @return этап
     */
    private RouteItemUser getRouteItemUser(RouteItemUser item) {
        RouteItemUser routeItemUser = new RouteItemUser();
        routeItemUser.setTypeID(item.getTypeID());
        routeItemUser.setName(item.getName());
        routeItemUser.setWorkloadValue(item.getWorkloadValue());
        routeItemUser.setWorkLoadType(item.getWorkLoadType());
        routeItemUser.setLengthType(item.getLengthType());
        routeItemUser.setLength(item.getLength());
        routeItemUser.setCompletionFormID(item.getCompletionFormID());
        routeItemUser.setReturnNumber(item.getReturnNumber());
        if (item.getTypeID().equals(RoutesConst.Processes.ROUTE)) {
            routeItemUser.setRouteID(item.getRouteID());
            routeItemUser.setRouteName(item.getRouteName());
        }
        return routeItemUser;
    }

}
