package kz.arta.synergy.workflow.mobile.android.files.activities;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.devspark.appmsg.AppMsg;
import com.google.gson.reflect.TypeToken;
import com.pnikosis.materialishprogress.ProgressWheel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
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.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.MyApplication;
import kz.arta.synergy.workflow.mobile.android.common.utils.Utils;
import kz.arta.synergy.workflow.mobile.android.files.FilesConst;
import kz.arta.synergy.workflow.mobile.android.files.manager.FilesRights;
import kz.arta.synergy.workflow.mobile.android.files.models.Node;
import kz.arta.synergy.workflow.mobile.android.files.offline.FilesFiltersTable;

/**
 * Created by neox on 27.10.15.
 * Дерево файлов и папок
 * Используется:
 * 1. Для перемещения ноды
 * 2. Для добавления файла из хранилища в работу/документ
 */
public class FilesTreeActivity extends Activity {

    /**
     * Активити
     */
    private Activity activity;

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

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

    /**
     * Контейнер, в котором находятся папки и файлы
     */
    private LinearLayout filesLayout;

    /**
     * Отображать ли файлы в списке
     */
    private boolean showFiles;

    /**
     * Выделенный пункт дерева
     */
    private FilesTree selectedItem;

    /**
     * Отображать только изображения
     */
    private boolean onlyImages;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.files_tree_activity);

        activity = this;

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

        Intent intent = getIntent();
        person = (Person) intent.getSerializableExtra(ActivityConst.PERSON);
        showFiles = intent.getBooleanExtra(FilesConst.SHOW_FILES, true);
        onlyImages = intent.getBooleanExtra(FilesConst.ONLY_IMAGES, false);

        TextView titleActivity = (TextView) findViewById(R.id.files_tree_action_bar_title);
        if (showFiles) {
            titleActivity.setText(R.string.from_storage);
        } else {
            titleActivity.setText(R.string.move);
        }

        progressBar = (ProgressWheel) findViewById(R.id.files_tree_progress_bar);

        filesLayout = (LinearLayout) findViewById(R.id.files_tree_layout);

        Button selectButton = (Button) findViewById(R.id.files_tree_select_button);
        selectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (selectedItem != null) {
                    Intent intent = new Intent();
                    intent.putExtra(FilesConst.NODE, selectedItem.getNode());
                    setResult(RESULT_OK, intent);
                    finish();
                } else if (showFiles) {
                    AppMsg.makeText(activity, getString(R.string.file_not_selected), AppMsg.STYLE_ALERT).show();
                } else {
                    AppMsg.makeText(activity, getString(R.string.folder_not_selected), AppMsg.STYLE_ALERT).show();
                }
            }
        });

        // загрузка элементов в список
        getTree();
    }

    /**
     * Загрузка данных в дерево
     */
    private void getTree() {
        new SendGetRequest("rest/api/storage/list?getOnlyFolders=" +
                (showFiles ? "false" : "true") + "&locale=" + MyApplication.getLang(), person) {
            @Override
            protected void onPreExecute() {
                filesLayout.removeAllViews();
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    result = new FilesFiltersTable(getBaseContext()).get(person.getHost()
                            + "rest/api/storage/list?getOnlyFolders=true&locale=" + MyApplication.getLang());
                }
                try {
                    Node[] files = RestClient.getGson().fromJson(result, Node[].class);
                    for (Node node : files) {
                        FilesTree filesTree = new FilesTree(node.getName(), 1, node);
                        filesLayout.addView(filesTree);
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(activity, getString(R.string.error_to_get_files), AppMsg.STYLE_ALERT).show();
                    return;
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    class FilesTree extends LinearLayout {

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

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

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

        /**
         * Текущая нода
         */
        private Node node;

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

        /**
         * Фон плашки
         */
        private RelativeLayout background;

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

            super(activity);

            this.level = level;
            this.node = node;

            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.files_tree_item, null);
            background = (RelativeLayout) contentLayout.findViewById(R.id.files_tree_activity_background_item);
            contentLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    setSelected();
                }
            });

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

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

            // имя текущего элемента
            elementName = (TextView) contentLayout.findViewById(R.id.files_tree_item_name);
            elementName.setText(text);
            elementName.setTypeface(Fonts.getMedium(activity));

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

            elementName.setLayoutParams(params);

            addView(contentLayout);
        }

        private FilesTree getItem() {
            return this;
        }

        /**
         * Тап по плашке
         */
        public void setSelected() {
            // проверка прав на текущую ноду в зависимости от типа действия
            if ((!showFiles && node.is_folder() && !FilesRights.checkRight(node.getRight(), FilesRights.ADD)) ||
                    (showFiles && !node.is_folder() && !FilesRights.checkRight(node.getRight(), FilesRights.LOAD_DOCUMENT))) {
                AppMsg.makeText(activity, getString(R.string.access_denied), AppMsg.STYLE_ALERT).show();
                return;
            }
            // если текущий элемент - это папка и используется режим отображения файлов
            if (showFiles && node.is_folder()) {
                // если нода раскрыта - сворачиваем, и наоборот
                if (state) {
                    collapse();
                } else {
                    expand();
                }
                return;
            }
            if (selectedItem != null) {
                selectedItem.background.setBackgroundColor(getResources().getColor(R.color.item_list_attachment_color));
            }
            selectedItem = getItem();
            background.setBackgroundColor(getResources().getColor(R.color.selected_item_list_color));
        }

        /**
         * Сворачивание ноды
         */
        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() {
            new SendGetRequest("rest/api/storage/list?parentID=" + node.getIdentifier() +
                    "&getOnlyFolders=" + (showFiles ? "false" : "true") + "&locale=" + MyApplication.getLang(), person) {
                @Override
                protected void onPreExecute() {
                    progressBar.setVisibility(View.VISIBLE);
                    super.onPreExecute();
                }

                @Override
                protected void onPostExecute(String result) {
                    progressBar.setVisibility(View.GONE);
                    if (result == null) {
                        result = new FilesFiltersTable(activity.getBaseContext()).get(person.getHost() + "rest/api/storage/list?parentID="
                                + node.getIdentifier() + "&getOnlyFolders=true&locale=" + MyApplication.getLang());
                    }
                    try {
                        List<Node> files = RestClient.getGson().fromJson(result, new TypeToken<List<Node>>() {
                        }.getType());
                        List<Node> filteredFiles = new ArrayList<>();
                        for (Node node : files) {
                            if (onlyImages && !node.is_folder() && !node.getName().endsWith("png")
                                    && !node.getName().endsWith("jpg") && !node.getName().endsWith("gif")) {
                                continue;
                            }
                            filteredFiles.add(node);
                        }
                        Collections.sort(filteredFiles, new Comparator<Node>() {
                            @Override
                            public int compare(Node node1, Node node2) {
                                return node1.getName().compareTo(node2.getName());
                            }
                        });
                        Collections.sort(filteredFiles, new Comparator<Node>() {
                            @Override
                            public int compare(Node node1, Node node2) {
                                boolean b1 = node1.is_folder();
                                boolean b2 = node2.is_folder();
                                if (b1 && !b2) {
                                    return -1;
                                }
                                if (!b1 && b2) {
                                    return +1;
                                }
                                return 0;
                            }
                        });
                        if (filteredFiles.isEmpty()) {
                            icon.setVisibility(View.INVISIBLE);
                            return;
                        }
                        level++;
                        for (Node node : filteredFiles) {
                            FilesTree filesTree = new FilesTree(node.getName(), level, node);
                            addView(filesTree);
                        }
                    } catch (Exception exc) {
                        AppMsg.makeText(activity, activity.getString(R.string.error_to_get_files), AppMsg.STYLE_ALERT).show();
                        return;
                    }
                    super.onPostExecute(result);
                }
            }.execute();
            state = true;
            icon.setImageResource(R.drawable.filters_detailed);
        }

        public Node getNode() {
            return node;
        }

        public boolean isState() {
            return state;
        }

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