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

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
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.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.gson.reflect.TypeToken;

import java.util.ArrayList;
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.activities.SettingsActivity;
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.Fonts;
import kz.arta.synergy.workflow.mobile.android.common.utils.Utils;
import kz.arta.synergy.workflow.mobile.android.files.FilesConst;

/**
 * Created by neox on 11.01.17.
 * Фрагмент навигатора для реестров
 */
public class FragmentRegistryTree extends Fragment {

    private Person person;
    private Activity activity;
    private ListItem selectedItem;
    private LinearLayout registryLayout;
    private FragmentRegistryList fragmentRegistryList;
    private List<ListItem> folders = new ArrayList<>();
    private SwipeRefreshLayout swipeRefreshLayout;

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

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

        person = (Person) getArguments().getSerializable(ActivityConst.PERSON);
        activity = getActivity();
        registryLayout = (LinearLayout) view.findViewById(R.id.filters_list);
        swipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.refresh_filters);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getRegistries();
            }
        });

        (view.findViewById(R.id.sync_button_title)).setVisibility(View.GONE);
        (view.findViewById(R.id.sync_icon)).setVisibility(View.GONE);
        (view.findViewById(R.id.sync_button)).setVisibility(View.GONE);

        final TextView navigatorTitle = (TextView) view.findViewById(R.id.title_action_bar_filters);
        navigatorTitle.setTypeface(Fonts.getMedium(getActivity()));

        // кнопка "Настройка"
        CustomImageView settings = (CustomImageView) view.findViewById(R.id.icon_settings);
        settings.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), SettingsActivity.class);
                intent.putExtra(ActivityConst.PERSON, person);
                startActivity(intent);
            }
        });

        getRegistries();

        return view;
    }

    private void getRegistries() {
        new SendGetRequest("rest/api/registry/list/", person) {
            @Override
            protected void onPreExecute() {
                registryLayout.removeAllViews();
                super.onPreExecute();
            }
            @Override
            protected void onPostExecute(String result) {
                swipeRefreshLayout.setRefreshing(false);
                if (result == null) {
                    return;
                }
                try {
                    List<RegistryModel> registryList = RestClient.getGson().
                            fromJson(result, new TypeToken<List<RegistryModel>>(){}.getType());
                    for (int i = 0; i < registryList.size(); i++) {
                        ListItem listItem = new ListItem(registryList.get(i).getName(), 1, registryList.get(i));
                        listItem.setParents(new ArrayList<RegistryModel>());
                        registryLayout.addView(listItem);
                        if (i == 0) {
                            listItem.setSelected();
                        }
                    }
                } catch (Exception exc) {
                    // handling error ...
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    public class ListItem extends LinearLayout {

        /**
         * Имя текущего элемента
         */
        private TextView elementName;

        /**
         * Иконка показывающая раскрыта ли данная нода или нет
         */
        private ImageView icon;

        /**
         * Состояние (раскрыто/свернуто)
         */
        private boolean state;

        /**
         * Текущая нода
         */
        private RegistryModel registryModel;

        /**
         * Уровень вложенности текущего элемента
         */
        private int level;

        /**
         * Родители текущей ноды
         */
        private List<RegistryModel> parents;

        /**
         * Конструктор
         *
         * @param text          имя папки
         * @param level         уровень вложенности
         * @param registryModel реестр
         */
        public ListItem(String text, int level, RegistryModel registryModel) {

            super(activity);

            this.level = level;
            this.registryModel = registryModel;

            setOrientation(LinearLayout.VERTICAL);
            setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));

            LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            RelativeLayout contentLayout = (RelativeLayout) layoutInflater.inflate(R.layout.filters_item, null);
            contentLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    setSelected();
                    ((MainActivity) activity).getFiltersSlidingMenu().toggle();
                }
            });

            // иконка
            icon = (ImageView) contentLayout.findViewById(R.id.icon_filter);
            icon.setOnClickListener(new ItemClickListener());

            // если текущий элемент - это файл, иконку отображать не нужно
            if (registryModel.getConsistOf() == null) {
                icon.setVisibility(View.INVISIBLE);
            }

            // имя элемента
            elementName = (TextView) contentLayout.findViewById(R.id.name_filter);
            elementName.setText(text);
            elementName.setTypeface(Fonts.getMedium(activity));
            elementName.setTextColor(getResources().getColor(R.color.not_selected_filter_item));

            // отступ слева (уровень вложеннсоти)
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) elementName.getLayoutParams();
            params.setMargins(Utils.dpToPx(FilesConst.DP_MARGIN_LEFT, activity) *
                    (level < FilesConst.OFFSET_LEVELS ? level : FilesConst.OFFSET_LEVELS), 0, 0, 0);

            elementName.setLayoutParams(params);

            addView(contentLayout);
        }

        /**
         * Тап по плашке
         */
        public void setSelected() {
            if (selectedItem != null) {
                selectedItem.elementName.setTextColor(Color.LTGRAY);
            }
            selectedItem = ListItem.this;
            elementName.setTextColor(getResources().getColor(R.color.selected_filter_item));
            fragmentRegistryList.getList(registryModel);
        }

        /**
         * Сворачивание ноды
         */
        public void collapse() {
            level--;
            for (int i = getChildCount() - 1; i >= 1; i--) {
                removeViewAt(i);
            }
            state = false;
            icon.setImageResource(R.drawable.filters_undetailed);
        }

        /**
         * Разворачивание текущей ноды
         */
        public void expand() {
            level++;
            List<RegistryModel> parentNodes = new ArrayList<>();
            parentNodes.add(registryModel);
            for (RegistryModel node : parents) {
                parentNodes.add(node);
            }
            for (RegistryModel regModel : registryModel.getConsistOf()) {
                ListItem listItem = new ListItem(regModel.getName(), level, regModel);
                listItem.setParents(parentNodes);
                addView(listItem);
            }
            state = true;
            icon.setImageResource(R.drawable.filters_detailed);
        }

        public boolean isState() {
            return state;
        }

        /**
         * Тап по изображению
         */
        private class ItemClickListener implements OnClickListener {
            public void onClick(View view) {
                if (state) {
                    collapse();
                } else {
                    expand();
                }
            }
        }

        public List<RegistryModel> getParents() {
            return parents;
        }

        public void setParents(List<RegistryModel> parents) {
            this.parents = parents;
        }
    }

    public void setFragmentRegistryList(FragmentRegistryList fragmentRegistryList) {
        this.fragmentRegistryList = fragmentRegistryList;
    }

    /**
     * Метод возвращает ноду в дереве по ее идентификатору
     *
     * @param layout контейнер, в котором находится список
     * @param nodeID идентификатор ноды
     */
    private void getNodeById(LinearLayout layout, String nodeID) {
        for (int i = 0; i < layout.getChildCount(); i++) {
            if (layout.getChildAt(i) instanceof ListItem) {
                ListItem node = (ListItem) layout.getChildAt(i);
                if (node.registryModel.getIdentifier().equals(nodeID)) {
                    folders.add(node);
                }
                getNodeById(node, nodeID);
            }
        }
    }

    public ListItem getCurrentNode() {
        if (folders.isEmpty()) {
            return null;
        } else {
            return folders.get(0);
        }
    }

    /**
     * Метод возвращает ноду в дереве по ее идентификатору
     *
     * @param nodeID идентификатор ноды
     */
    public void getNodeById(String nodeID) {
        folders.clear();
        getNodeById(registryLayout, nodeID);
    }

    /**
     * Метод ищет в дереве ноду с идентификатором nodeID и разворает/сворачивает ее (в зависимости от переданного параметра expand)
     *
     * @param layout контейнер, в котором находится список
     * @param nodeID идентификатор ноды
     * @param expand true - раскрыавем дерево, false - сворачиваем
     */
    private void expandNode(LinearLayout layout, String nodeID, boolean expand) {
        for (int i = 0; i < layout.getChildCount(); i++) {
            if (layout.getChildAt(i) instanceof ListItem) {
                ListItem node = (ListItem) layout.getChildAt(i);
                // если нода нашлась
                if (node.registryModel.getIdentifier().equals(nodeID)) {
                    // если используется раскрытие
                    if (expand) {
                        // если текущая нода не раскрыта
                        if (!node.isState()) {
                            // раскрываем ее
                            node.expand();
                            node.setSelected(false);
                        }
                    } else {
                        // сворачивание ноды
                        if (node.isState()) {
                            node.collapse();
                        }
                    }
                    return;
                }
                expandNode(node, nodeID, expand);
            }
        }
    }

    /**
     * Метод используется для обновления ноды
     *
     * @param nodeID идентификатор ноды
     */
    public void updateNode(String nodeID) {
        expandNode(registryLayout, nodeID, true);
    }
}
