package kz.arta.synergy.workflow.mobile.android.registry;

import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.devspark.appmsg.AppMsg;
import com.pnikosis.materialishprogress.ProgressWheel;

import org.json.JSONArray;
import org.json.JSONObject;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
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.activities.MainActivity;
import kz.arta.synergy.workflow.mobile.android.common.components.CustomImageView;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.requests.RestClient;
import kz.arta.synergy.workflow.mobile.android.common.requests.SendGetRequest;
import kz.arta.synergy.workflow.mobile.android.common.utils.ActionUtils;
import kz.arta.synergy.workflow.mobile.android.common.utils.FragmentConst;
import kz.arta.synergy.workflow.mobile.android.common.utils.HorizontalListView;
import kz.arta.synergy.workflow.mobile.android.documents.common.models.DocumentItem;
import kz.arta.synergy.workflow.mobile.android.documents.favorite.models.FavoriteItem;
import kz.arta.synergy.workflow.mobile.android.documents.route.RouteManager;
import kz.arta.synergy.workflow.mobile.android.documents.route.RoutesConst;
import kz.arta.synergy.workflow.mobile.android.documents.route.activities.RouteActivity;
import kz.arta.synergy.workflow.mobile.android.documents.route.models.Routes;
import kz.arta.synergy.workflow.mobile.android.files.adapters.AdapterPath;
import kz.arta.synergy.workflow.mobile.android.files.models.Path;
import kz.arta.synergy.workflow.mobile.android.forms.general.activities.FormPlayer;
import kz.arta.synergy.workflow.mobile.android.forms.general.components.registrychooser.RegistryChooserAdapter;
import kz.arta.synergy.workflow.mobile.android.forms.general.components.registrychooser.RegistryChooserDialog;
import kz.arta.synergy.workflow.mobile.android.forms.general.components.registrychooser.RegistryListAdapter;
import kz.arta.synergy.workflow.mobile.android.forms.general.components.registrychooser.models.RegistryDataModel;
import kz.arta.synergy.workflow.mobile.android.forms.general.components.registrychooser.models.RegistryInfoModel;

/**
 * Created by neox on 11.01.17.
 * Фрагмент списка записей реестра
 */
public class FragmentRegistryList extends Fragment {

    /**
     * Авторизированный пользователь
     */
    private Person person;

    /**
     * Данные списка
     */
    private List<List<RegistryDataModel.Data>> data;

    /**
     * Адаптер
     */
    private ArrayAdapter adapter;

    /**
     * Тип отображения плашек (true - полный вид, false - только значащее содержимое)
     */
    private boolean showAll;

    /**
     * Информация о колонках
     */
    private RegistryInfoModel regInfo;

    /**
     * Прогрессбар
     */
    private ProgressWheel progressBar;

    /**
     * Диалог
     */
    private RegistryChooserDialog dialog;

    /**
     * Колонка по которое производится фильтрация
     */
    private RegistryInfoModel.Columns filteredColumn;

    /**
     * Номер страницы
     */
    private int pageNumber = 0;

    /**
     * Загружается ли список в данный момент
     */
    private boolean isLoading = false;

    /**
     * Идентификатор текущего реестра
     */
    private String registryID;

    /**
     * View
     */
    private View view;

    /**
     * ListView
     */
    private ListView list;

    /**
     * Компонент "Путь"
     */
    private HorizontalListView pathList;

    /**
     * Данные компонента "Путь"
     */
    private List<Path> pathData;

    /**
     * Адаптер компонента "Путь"
     */
    private BaseAdapter pathAdapter;

    private FragmentRegistryTree fragmentRegistryTree;

    private RegistryModel registry;

    private String searchRegistryID;

    private SwipeRefreshLayout swipeRefreshLayout;

    private int pos = -1;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.registry_list_activity, null);

        person = (Person) getArguments().getSerializable(ActivityConst.PERSON);

        searchRegistryID = getArguments().getString(ActivityConst.REGISTRY);

        progressBar = (ProgressWheel) view.findViewById(R.id.registry_fragment_progress_bar);

        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh_layout_registry);

        data = new ArrayList<>();

        init();

        return view;

    }

    /**
     * Инициализация списка
     */
    private void init() {

        if (searchRegistryID == null) {
            CustomImageView menuButton = (CustomImageView) getActivity().findViewById(R.id.icon_menu);
            menuButton.setVisibility(View.VISIBLE);
            menuButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    showDialog();
                }
            });
        }

        dialog = (RegistryChooserDialog) view.findViewById(R.id.registry_chooser_activity_dialog);
        dialog.addRegistryCallBack(new RegistryChooserDialog.RegistryCallBack() {
            @Override
            public void onSelect(RegistryInfoModel.Columns field) {
                filteredColumn = field;
                pageNumber = 0;
                getData("", true, true);
            }
        });

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                pageNumber = 0;
                getData("", false, true);
            }
        });

        list = (ListView) view.findViewById(R.id.registry_chooser_activity_list);
        list.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (totalItemCount >= FragmentConst.DEFAULT_COUNT_WORKS) {
                    final int lastItem = firstVisibleItem + visibleItemCount;
                    if (lastItem == totalItemCount && !isLoading) {
                        isLoading = true;
                        pageNumber += 1;
                        getData("", false, false);
                    }
                }
            }
        });

        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                pos = position;
                if (registry == null) {
                    Intent intent = new Intent(getActivity(), FormPlayer.class);
                    intent.putExtra(ActivityConst.DATA_UUID, data.get(position).get(0).getDataUUID());
                    intent.putExtra(ActivityConst.PERSON, person);
                    intent.putExtra(ActivityConst.CAN_EDIT, (data.get(pos).get(0).getState() == 1 ? "false" : "true"));
                    startActivity(intent);
                } else {
                    if (registry.getConsistOf() == null) {
                        if (!Arrays.asList(registry.getRights()).contains("rr_read")) {
                            return;
                        }
                        try {
                            Intent intent = new Intent(getActivity(), FormPlayer.class);
                            intent.putExtra(ActivityConst.DATA_UUID, data.get(position).get(0).getDataUUID());
                            intent.putExtra(ActivityConst.PERSON, person);
                            if (data.get(pos).get(0).getState() == 2) {
                                intent.putExtra(ActivityConst.CAN_EDIT, (Arrays.asList(registry.getRights()).contains("rr_modify") ? "true" : "false"));
                            } else {
                                intent.putExtra(ActivityConst.CAN_EDIT, (data.get(pos).get(0).getState() == 1 ? "false" : "true"));
                            }
                            startActivityForResult(intent, ActionUtils.SAVE_FORM);
                        } catch (Exception exc) {
                            // handling error
                        }
                    } else if (registry.getConsistOf().get(position).getConsistOf() != null) {
                        try {
                            fragmentRegistryTree.updateNode(registry.getRegGroupID());
                            fragmentRegistryTree.getNodeById(registry.getConsistOf().get(position).getRegGroupID());
                            fragmentRegistryTree.getCurrentNode().setSelected();
                        } catch (Exception exc) {
                            // handling error
                        }
                    } else {
                        try {
                            fragmentRegistryTree.updateNode(registry.getRegGroupID());
                            fragmentRegistryTree.getNodeById(registry.getConsistOf().get(position).getRegistryID());
                            fragmentRegistryTree.getCurrentNode().setSelected();
                        } catch (Exception exc) {
                            // handling error ...
                        }
                    }
                }
            }
        });

        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                pos = position;
                shoeLongTapDialog(position);
                return true;
            }
        });

        if (searchRegistryID == null) {
            // данные для компонента "путь"
            pathData = new ArrayList<>();
            // адаптер для компонента "путь"
            pathAdapter = new AdapterPath(getActivity(), pathData);
            // сам компонент "путь"
            pathList = (HorizontalListView) view.findViewById(R.id.list_view_path);
            // связываем адаптер со списком
            pathList.setAdapter(pathAdapter);
            // тап по плашке компонента "путь"
            pathList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    // все элементы отмечаем как "невыделенные"
                    for (Path path : pathData) {
                        path.setSelected(false);
                    }
                    // говорим элемент, по которому происходит тап - будет выделен
                    pathData.get(i).setSelected(true);
                    // получаем описание ноды по ее идентификатору
                    fragmentRegistryTree.getNodeById(pathData.get(i).getNodeID());
                    // выделяем ноду в дереве
                    fragmentRegistryTree.getCurrentNode().setSelected();
                }
            });
            view.findViewById(R.id.layout_list_view_path).setVisibility(View.VISIBLE);
        } else {
            showAll = true;
            registryID = searchRegistryID;
            getInfo();
        }
    }

    /**
     * Метод заполняет данными компонент "путь"
     */
    private void initPath() {
        // очистка пути
        pathData.clear();
        // получение текущего выделенного элемента
        fragmentRegistryTree.getNodeById(registry.getIdentifier());
        // если есть родители
        if (fragmentRegistryTree.getCurrentNode() != null) {
            // пробегаемся по всем существующим родителям и добавляем в список
            for (int i = fragmentRegistryTree.getCurrentNode().getParents().size() - 1; i >= 0; i--) {
                // объект "элемент пути"
                Path path = new Path();
                // идентификатор папки
                path.setNodeID(fragmentRegistryTree.getCurrentNode().getParents().get(i).getIdentifier());
                // имя папки
                path.setName(fragmentRegistryTree.getCurrentNode().getParents().get(i).getName());
                // добавление папки в основной массив
                pathData.add(path);
            }
        }
        // объект "элемент пути"
        Path path = new Path();
        // идентификатор папки
        path.setNodeID(registry.getIdentifier());
        // имя папки
        path.setName(registry.getName());
        // делаем активным последний элемент
        path.setSelected(true);
        // добавление папки в основной массив
        pathData.add(path);
        // обновляем компонент
        pathAdapter.notifyDataSetChanged();
        // скроллим список до конца
        pathList.scrollTo(Integer.MAX_VALUE);
    }

    /**
     * Получение списка реестров либо записей реестра
     *
     * @param registry объект класса RegistryModel
     */
    public void getList(RegistryModel registry) {
        this.registry = registry;
        LinearLayout icons = (LinearLayout) getActivity().findViewById(R.id.main_activity_right_icon_layout);
        if (registry.getConsistOf() != null) {
            icons.setVisibility(View.GONE);
            adapter = new RegistryListAdapter(getActivity(), registry.getConsistOf());
            list.setAdapter(adapter);
            initPath();
            progressBar.setVisibility(View.GONE);
        } else {
            icons.setVisibility(View.VISIBLE);
            registryID = registry.getRegistryID();
            pageNumber = 0;
            getInfo();
        }
    }

    /**
     * Получение описание реестра
     */
    private void getInfo() {
        new SendGetRequest("rest/api/registry/info?registryID=" + registryID, person) {
            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    AppMsg.makeText(getActivity(), getString(R.string.error_to_get_registry_info), AppMsg.STYLE_ALERT).show();
                    return;
                }
                try {
                    regInfo = RestClient.getGson().fromJson(result, RegistryInfoModel.class);
                    if (regInfo != null) {
                        adapter = new RegistryChooserAdapter(getActivity(), data, showAll, regInfo);
                        list.setAdapter(adapter);
                        getData("", true, true);
                    } else {
                        AppMsg.makeText(getActivity(), getString(R.string.error_to_get_registry_info), AppMsg.STYLE_ALERT).show();
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(getActivity(), getString(R.string.error_to_get_registry_info), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Получение списка записей реестра
     *
     * @param search строка поиска
     */
    public void getData(String search) {
        getData(search, true, true);
    }

    /**
     * Получение списка записей реестра
     *
     * @param search          строка поиска
     * @param showProgressBar показывать прогрессбар
     * @param clearList       очищать список или нет
     */
    private void getData(String search, final boolean showProgressBar, final boolean clearList) {
        try {
            search = URLEncoder.encode(search, "utf-8");
        } catch (Exception ignored) {}
        String filtered = "";
        if (filteredColumn != null) {
            filtered = "&sortCmpID=" + filteredColumn.getColumnID() + "&sortDesc=" + !filteredColumn.isUpIcon();
        }
        new SendGetRequest("rest/api/registry/data_ext?registryID=" + registryID +
                "&pageNumber=" + pageNumber +
                "&countInPart=" + FragmentConst.DEFAULT_COUNT_WORKS +
                "&searchString=" + search + filtered, person) {
            @Override
            protected void onPreExecute() {
                if (showProgressBar) {
                    progressBar.setVisibility(View.VISIBLE);
                }
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                if (swipeRefreshLayout.isRefreshing()) {
                    swipeRefreshLayout.setRefreshing(false);
                }
                if (showProgressBar) {
                    progressBar.setVisibility(View.GONE);
                }
                if (result == null) {
                    AppMsg.makeText(getActivity(), getString(R.string.error_to_get_registry_data), AppMsg.STYLE_ALERT).show();
                    return;
                }
                try {
                    if (clearList) {
                        data.clear();
                    }
                    JSONObject jsonObject = new JSONObject(result);
                    JSONArray resultArray = jsonObject.getJSONArray("result");
                    for (int i = 0; i < resultArray.length(); i++) {
                        JSONObject registryObject = resultArray.getJSONObject(i);
                        String documentID = registryObject.getString("documentID");
                        String dataUUID = registryObject.getString("dataUUID");
                        int state = registryObject.getInt("state");
                        JSONObject fieldsValue = registryObject.getJSONObject("fieldValue");
                        List<RegistryDataModel.Data> buf = new ArrayList<>();
                        if (fieldsValue != null && fieldsValue.names() != null) {
                            for (int j = 0; j < fieldsValue.names().length(); j++) {
                                String key = fieldsValue.names().getString(j);
                                String value = fieldsValue.getString(fieldsValue.names().getString(j));
                                RegistryDataModel.Data data = new RegistryDataModel.Data();
                                data.setUuid(documentID);
                                data.setCmp_id(key);
                                data.setCmp_data(value);
                                data.setDataUUID(dataUUID);
                                data.setState(state);
                                buf.add(data);
                            }
                            data.add(buf);
                        } else {
                            RegistryDataModel.Data data = new RegistryDataModel.Data();
                            data.setDataUUID(dataUUID);
                            data.setState(state);
                            buf.add(data);
                            FragmentRegistryList.this.data.add(buf);
                        }
                    }
                    isLoading = resultArray.length() == 0;
                    adapter.notifyDataSetChanged();
                    if (searchRegistryID == null) {
                        initPath();
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(getActivity(), getString(R.string.error_to_get_registry_data), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Отображение меню
     */
    private void showDialog() {
        String[] array = {(showAll ? "Краткий" : "Полный"), "Сортировка", "Поиск"};
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
        alertDialog.setItems(array, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int which) {
                switch (which) {
                    case 0: {
                        showAll = !showAll;
                        if (registry.getConsistOf() == null) {
                            ((RegistryChooserAdapter) adapter).setShowAll(showAll);
                            adapter.notifyDataSetChanged();
                        }
                        break;
                    }
                    case 1: {
                        dialog.setShowAll(showAll);
                        dialog.setColumns(regInfo.getColumns());
                        dialog.showDialog();
                        break;
                    }
                    case 2: {
                        if (registry.getRegistryID() != null) {
                            Intent intent = new Intent(getActivity(), RegistrySearchActivity.class);
                            intent.putExtra(ActivityConst.REGISTRY, registry.getRegistryID());
                            intent.putExtra(ActivityConst.PERSON, person);
                            startActivity(intent);
                        }
                        break;
                    }
                }
            }
        });
        alertDialog.show();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        /*final int state = this.data.get(pos).get(0).getState();
        if (resultCode != Activity.RESULT_CANCELED && requestCode == ActionUtils.SAVE_FORM && state == 2) {
            removeRegistryRecord(pos, RoutesConst.CHANGE);
        }*/
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Отображение действий при долгом нажатии на плашку
     *
     * @param position номер записи
     */
    private void shoeLongTapDialog(final int position) {
        if (registry.getConsistOf() != null) {
            return;
        }
        if (!Arrays.asList(registry.getRights()).contains("rr_delete")) {
            return;
        }
        if (data.get(position).get(0).getState() == 1) {
            return;
        }
        String[] array = {getString(R.string.delete)};
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
        alertDialog.setItems(array, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int which) {
                switch (which) {
                    case 0: {
                        showRemoveDialog(position);
                        break;
                    }
                }
            }
        });
        alertDialog.show();
    }

    /**
     * Отображение диалога удаления
     *
     * @param position номер записи
     */
    private void showRemoveDialog(final int position) {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
        alertDialog.setMessage(R.string.remove_item_registry_question);
        alertDialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                removeRegistryRecord(position, RoutesConst.DELETE);
            }
        });
        alertDialog.setNegativeButton(R.string.no, null);
        alertDialog.show();
    }

    /**
     * Удаление записи реестра
     *
     * @param position номер записи
     * @param type     тип действия
     */
    private void removeRegistryRecord(final int position, final String type) {
        if (registry == null) {
            return;
        }
        final String dataUUID = data.get(position).get(0).getDataUUID();
        final String documentID = data.get(position).get(0).getUuid();
        final String registryID = registry.getRegistryID();
        new SendGetRequest("rest/api/registry/route?registryID=" + registryID + "&type=" + type, person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.error_to_get_routes), AppMsg.STYLE_ALERT).show();
                    return;
                }
                if (result.equals("[]")) {
                    startEmptyRoute(dataUUID);
                } else {
                    Routes routes = RestClient.getGson().fromJson(result, Routes.class);
                    DocumentItem document = new DocumentItem();
                    document.setDocumentID(documentID);
                    document.setAsfDataID(dataUUID);
                    document.setRegistryID(registryID);
                    document.setFormName("form");
                    RouteManager routeManager = new RouteManager(routes, document, person, getActivity(), type);
                    if (routeManager.isShowActivity()) {
                        Intent intent = new Intent(getActivity(), RouteActivity.class);
                        intent.putExtra(ActivityConst.PERSON, person);
                        intent.putExtra(ActivityConst.DOCUMENT, document);
                        intent.putExtra(RoutesConst.ROUTES, routes);
                        intent.putExtra(RoutesConst.ROUTE_TYPE, type);
                        getActivity().startActivityForResult(intent, ActionUtils.ROUTE_START);
                    } else {
                        routeManager.startRoute(progressBar);
                    }
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Запуск маршрута без этапов
     *
     * @param dataUUID идентификатор данных по форме
     */
    private void startEmptyRoute(String dataUUID) {
        new SendGetRequest("rest/api/registry/delete_doc?dataUUID=" + dataUUID, person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    return;
                }
                getData("");
                super.onPostExecute(result);
            }
        }.execute();
    }

    public void setFragmentRegistryTree(FragmentRegistryTree fragmentRegistryTree) {
        this.fragmentRegistryTree = fragmentRegistryTree;
    }

    /**
     * Создание новой записи
     */
    public void createNewRecord() {
        FavoriteItem favoriteItem = new FavoriteItem();
        favoriteItem.setRegistryID(registryID);
        MainActivity activity = (MainActivity) getActivity();
        activity.createDocument(favoriteItem);
    }

    public RegistryModel getRegistry() {
        return registry;
    }
}
