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

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;

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

import java.io.File;
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.SettingsConst;
import kz.arta.synergy.workflow.mobile.android.common.activities.MainActivity;
import kz.arta.synergy.workflow.mobile.android.common.components.OpenFileDialog;
import kz.arta.synergy.workflow.mobile.android.common.models.ErrorCode;
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.Const;
import kz.arta.synergy.workflow.mobile.android.common.utils.FragmentBackPressedListener;
import kz.arta.synergy.workflow.mobile.android.common.utils.HorizontalListView;
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.common.utils.Wrapper;
import kz.arta.synergy.workflow.mobile.android.files.FilesConst;
import kz.arta.synergy.workflow.mobile.android.files.activities.FilesTreeActivity;
import kz.arta.synergy.workflow.mobile.android.files.adapters.AdapterFiles;
import kz.arta.synergy.workflow.mobile.android.files.adapters.AdapterPath;
import kz.arta.synergy.workflow.mobile.android.files.manager.DownloadFile;
import kz.arta.synergy.workflow.mobile.android.files.manager.FileUpload;
import kz.arta.synergy.workflow.mobile.android.files.manager.FilesManager;
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.models.Path;
import kz.arta.synergy.workflow.mobile.android.files.offline.FilesListTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.actions.FilesAddFileTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.actions.FilesMoveTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.actions.FilesNewFolderTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.actions.FilesRemoveTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.actions.FilesRenameTable;

/**
 * Created by neox on 01.11.14.
 * Список файлов и папок
 */
public class FragmentFilesList extends Fragment {

    /**
     * Список файлов
     */
    private List<Node> data;

    /**
     * Адаптер отвечающий за работу списка
     */
    private BaseAdapter adapter;

    /**
     * Прогрессбар (отображается при загрузке списка файлов)
     */
    private ProgressWheel progressBar;

    /**
     * Обновление спика документов свайпом
     */
    private SwipeRefreshLayout refreshLayout;

    /**
     * Настройки
     */
    private SharedPreferences settings;

    /**
     * Содержимое текущего фрагмента
     */
    private View view;

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

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

    /**
     * Запросы на сервер
     */
    private FilesManager manager;

    /**
     * Фрагмент содержащий в себе дерево папок
     */
    private FragmentFilesTree fragmentTree;

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

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

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

    /**
     * Индекс выделенного элемента
     */
    private int selectedIndex;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_list_files, null);
        init();
        // нажатие на кнопку "back"
        ((MainActivity) getActivity()).setFragmentBackPressedListener(new FragmentBackPressedListener() {
            @Override
            public void doBack() {
                if (((MainActivity) getActivity()).getFiltersSlidingMenu().isMenuShowing()) {
                    ((MainActivity) getActivity()).getFiltersSlidingMenu().toggle();
                } else {
                    backPressed();
                }
            }
        });
        return view;
    }

    /**
     * Инициализация компонентов
     */
    private void init() {
        // настройки
        settings = getActivity().getSharedPreferences(SettingsConst.DEFAULT_NAME_SETTINGS, Context.MODE_PRIVATE);
        // пользователь
        person = (Person) getArguments().getSerializable(ActivityConst.PERSON);
        // класс для отправки запросов на сервер
        manager = new FilesManager(person);
        // прогрессбар
        progressBar = (ProgressWheel) view.findViewById(R.id.main_fragment_progress_bar);
        // компонент для обновления списка файлов свайпом
        refreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh_files);
        // цветовая схема компонента
        refreshLayout.setColorSchemeResources(R.color.color1_update_list, R.color.color2_update_list,
                R.color.color3_update_list, R.color.color4_update_list);
        // что будет происходить при обновлении списка
        refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        getFiles(node, false, false);
                    }
                }, 0);
            }
        });
        // список файлов и папок
        ListView list = (ListView) view.findViewById(R.id.list_files);
        // тап по списку
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                selectedIndex = position;
                // если папка - проваливаемся в нее, если файл - загружаем на устройство и открываем
                if (data.get(position).is_folder()) {
                    // обновление дерева
                    fragmentTree.updateNode(node.getIdentifier());
                    // обновляем список файлов
                    getFiles(data.get(position), true, true);
                } else {
                    // право на загрузку
                    if (FilesRights.checkRight(node.getRight(), FilesRights.LOAD_DOCUMENT)) {
                        // загружаем файл на устройство и открываем
                        getFile(data.get(position).getIdentifier(), true);
                    }
                }
            }
        });
        // долгий тап по списку
        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {
                selectedIndex = position;
                showDialog(data.get(position));
                return true;
            }
        });
        // данные списка файлов
        data = new ArrayList<>();
        // адаптер списка файлов
        adapter = new AdapterFiles(getActivity(), data, person);
        // связываем адаптер со списком
        list.setAdapter(adapter);
        // данные для компонента "путь"
        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);
                // получаем описание ноды по ее идентификатору
                fragmentTree.getNodeById(pathData.get(i).getNodeID());
                // выделяем ноду в дереве
                fragmentTree.getCurrentNode().setSelected(true);
            }
        });
    }

    /**
     * Метод вызывается при долгом нажатии на плашку (отображение диалога)
     *
     * @param node описание текущего элемента
     */
    private void showDialog(final Node node) {
        // здесь хранятся имена элементов контестного меню
        final List<String> items = new ArrayList<>();
        // здесь хранятся права
        final List<Integer> rights = new ArrayList<>();
        // право на переименование
        if (FilesRights.checkRight(node.getRight(), FilesRights.MOVE)) {
            items.add(getActivity().getString(R.string.rename));
            rights.add(FilesRights.MOVE);
        }
        // право на перемещение
        if (FilesRights.checkRight(node.getRight(), FilesRights.MOVE)) {
            items.add(getActivity().getString(R.string.move));
            rights.add(FilesRights.MOVE + 1);
        }
        // право на загрузку
        if (FilesRights.checkRight(node.getRight(), FilesRights.LOAD_DOCUMENT) && !node.is_folder()) {
            items.add(getActivity().getString(R.string.download));
            rights.add(FilesRights.LOAD_DOCUMENT);
        }
        // право на загрузку
        if (FilesRights.checkRight(node.getRight(), FilesRights.LOAD_DOCUMENT) && !node.is_folder()
                && (node.getAi_type().equals(FilesConst.AI_DOCUMENT) || node.getAi_type().equals(FilesConst.AI_HTD_DOCUMENT))) {
            items.add(getActivity().getString(R.string.download_pdf));
            rights.add(FilesRights.LOAD_DOCUMENT + 1);
        }
        // право на удаление
        if (FilesRights.checkRight(node.getRight(), FilesRights.DELETE)) {
            items.add(getActivity().getString(R.string.delete));
            rights.add(FilesRights.DELETE);
        }
        // отображение диалога
        AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
        dialog.setTitle(getResources().getString(R.string.actions));
        dialog.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, final int pos) {
                switch (rights.get(pos)) {
                    // удаление
                    case FilesRights.DELETE: {
                        showRemoveDialog(node);
                        break;
                    }
                    // загрузка
                    case FilesRights.LOAD_DOCUMENT: {
                        getFile(node.getIdentifier(), false);
                        break;
                    }
                    // загрузка pdf
                    case FilesRights.LOAD_DOCUMENT + 1: {
                        getFile(node.getIdentifier(), true);
                        break;
                    }
                    // переименование
                    case FilesRights.MOVE: {
                        showRenameDialog(node, node.getName());
                        break;
                    }
                    // перемещение
                    case FilesRights.MOVE + 1: {
                        openMoveActivity(node.getIdentifier());
                        break;
                    }
                }
            }
        });
        dialog.setCancelable(true);
        // если есть хоть одно право - отображаем диалог
        if (!items.isEmpty()) {
            dialog.show();
        }
    }

    /**
     * Метод открывает активити для перемещения ноды
     *
     * @param nodeID идентификатор ноды
     */
    private void openMoveActivity(String nodeID) {
        Intent intent = new Intent(getActivity(), FilesTreeActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(FilesConst.SHOW_FILES, false);
        intent.putExtra(FilesConst.NODE_ID, nodeID);
        startActivityForResult(intent, ActionUtils.UPLOAD_FILE_FROM_STORAGE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_CANCELED) {
            return;
        }
        if (requestCode == ActionUtils.UPLOAD_FILE_FROM_STORAGE) {
            final Node node = (Node) data.getSerializableExtra(FilesConst.NODE);
            if (node == null) {
                return;
            }
            move(node);
        }
    }

    /**
     * Метод отображает диалог для удаления ноды
     *
     * @param node описание ноды
     */
    private void showRemoveDialog(final Node node) {
        AlertDialog.Builder ad = new AlertDialog.Builder(getActivity());
        if (node.is_folder()) {
            ad.setMessage(getActivity().getString(R.string.remove_folder_question) + node.getName() + "\"?");
        } else {
            ad.setMessage(getActivity().getString(R.string.remove_file_question) + node.getName() + "\"?");
        }
        ad.setTitle(R.string.removing_element);
        ad.setPositiveButton(getActivity().getString(R.string.yes), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int arg1) {
                remove(node);
            }
        });
        ad.setNegativeButton(getActivity().getString(R.string.no), null);
        ad.setCancelable(true);
        ad.show();
    }

    /**
     * Метод отображает диалог для дпереименования ноды
     *
     * @param node     нода
     * @param nodeName новое имя ноды
     */
    private void showRenameDialog(final Node node, final String nodeName) {
        final EditText input = new EditText(getActivity());
        input.setInputType(InputType.TYPE_CLASS_TEXT);
        input.setText(nodeName);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(getActivity().getString(R.string.renaming));
        builder.setView(input);
        builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!input.getText().toString().isEmpty() && input.getText().toString().trim().length() > 0) {
                    rename(node, input.getText().toString());
                } else {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.enter_element_name), AppMsg.STYLE_ALERT).show();
                    showRenameDialog(node, "");
                }
            }
        });
        builder.setNegativeButton(R.string.cancel, null);
        builder.show();
    }

    /**
     * Отображение диалога для создания новой папки
     */
    public void showFolderDialog() {
        final EditText input = new EditText(getActivity());
        input.setInputType(InputType.TYPE_CLASS_TEXT);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(R.string.new_folder);
        builder.setView(input);
        builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!input.getText().toString().isEmpty() && input.getText().toString().trim().length() > 0) {
                    newFolder(input.getText().toString());
                } else {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.enter_folder_name), AppMsg.STYLE_ALERT).show();
                }
            }
        });
        builder.setNegativeButton(R.string.cancel, null);
        builder.show();
    }

    /**
     * Метод используется для перемещения элементов внутри хранилища
     *
     * @param currentNode нода
     */
    private void move(final Node currentNode) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                return manager.move(data.get(selectedIndex).getIdentifier(), currentNode.getIdentifier());
            }

            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        // добавляем действие для перемещения ноды
                        FilesMoveTable filesMoveTable = new FilesMoveTable(getActivity().getBaseContext());
                        filesMoveTable.add(data.get(selectedIndex).getIdentifier(), currentNode.getIdentifier(),
                                data.get(selectedIndex).getName(), currentNode.getName(), (data.get(selectedIndex).is_folder() ? "folder" : "file"));
                        // перемещаем ноду в списке
                        FilesListTable filesListTable = new FilesListTable(getActivity().getBaseContext());
                        filesListTable.moveNode(person.getHost() + "rest/api/storage/list?parentID=" +
                                        FragmentFilesList.this.node.getIdentifier() + "&locale=" + MyApplication.getLang(),
                                data.get(selectedIndex).getIdentifier(), person.getHost() + "rest/api/storage/list?parentID=" +
                                        currentNode.getIdentifier() + "&locale=" + MyApplication.getLang());
                        getFiles(FragmentFilesList.this.node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                    }
                    return;
                }
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.NO_ERROR)) {
                        getFiles(node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), errorCode.getErrorMessage(), AppMsg.STYLE_ALERT).show();
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.error_to_move_element), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод используется для удаления ноды
     *
     * @param node нода
     */
    private void remove(final Node node) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                return manager.remove(node.getIdentifier());
            }

            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        if (node.getIdentifier() == null) {
                            // добавляем действие для удаления фала
                            if (node.is_folder()) {
                                FilesNewFolderTable filesNewFolderTable = new FilesNewFolderTable(getActivity().getBaseContext());
                                filesNewFolderTable.removeByDate(node.getModified());
                            } else {
                                FilesAddFileTable filesAddFileTable = new FilesAddFileTable(getActivity().getBaseContext());
                                filesAddFileTable.removeByDate(node.getModified());
                            }
                        } else {
                            // удаляем файл из списка файлов
                            FilesListTable filesListTable = new FilesListTable(getActivity().getBaseContext());
                            filesListTable.removeNode(person.getHost() + "rest/api/storage/list?parentID=" +
                                    FragmentFilesList.this.node.getIdentifier() + "&locale=" + MyApplication.getLang(), node.getIdentifier());
                            // добавляем действие для удаления фала
                            FilesRemoveTable filesRemoveTable = new FilesRemoveTable(getActivity().getBaseContext());
                            filesRemoveTable.add(node.getIdentifier(), node.getName(), (node.is_folder() ? "folder" : "file"));
                        }
                        getFiles(FragmentFilesList.this.node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                    }
                    return;
                }
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.NO_ERROR)) {
                        getFiles(node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), errorCode.getErrorMessage(), AppMsg.STYLE_ALERT).show();
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.error_to_remove_element), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод используется для переименования ноды
     *
     * @param node    нода
     * @param newName новое имя
     */
    private void rename(final Node node, final String newName) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                return manager.rename(node.getIdentifier(), newName);
            }

            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        if (node.getIdentifier() == null) {
                            if (node.is_folder()) {
                                // переименовываем раннее добавленную папку
                                FilesNewFolderTable filesNewFolderTable = new FilesNewFolderTable(getActivity().getBaseContext());
                                filesNewFolderTable.renameByDate(node.getModified(), newName);
                            } else {
                                // переименовываем раннее добавленный файл
                                FilesAddFileTable filesAddFileTable = new FilesAddFileTable(getActivity().getBaseContext());
                                filesAddFileTable.renameByDate(node.getModified(), newName);
                            }
                        } else {
                            // переименовываем файл в списке файлов
                            FilesListTable filesListTable = new FilesListTable(getActivity().getBaseContext());
                            filesListTable.renameNode(person.getHost() + "rest/api/storage/list?parentID=" +
                                    FragmentFilesList.this.node.getIdentifier() + "&locale=" + MyApplication.getLang(), node.getIdentifier(), newName);
                            // добавляем действие для переименование файла
                            FilesRenameTable filesRenameTable = new FilesRenameTable(getActivity().getBaseContext());
                            filesRenameTable.add(node.getIdentifier(), newName, (node.is_folder() ? "folder" : "file"));
                        }
                        getFiles(FragmentFilesList.this.node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                    }
                    return;
                }
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.NO_ERROR)) {
                        getFiles(node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), errorCode.getErrorMessage(), AppMsg.STYLE_ALERT).show();
                    }
                } catch (Exception exc) {
                    AppMsg.makeText(getActivity(), getActivity().getString(R.string.error_to_rename_element), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод используется для создания новой папки
     *
     * @param name имя папки
     */
    private void newFolder(final String name) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                return manager.newFolder(node.getIdentifier(), name);
            }

            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        FilesNewFolderTable filesNewFolderTable = new FilesNewFolderTable(getActivity().getBaseContext());
                        filesNewFolderTable.add(node.getIdentifier(), name, person.getUserName(), node.getName());
                        getFiles(node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                    }
                    return;
                }
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.ERROR)) {
                        AppMsg.makeText(getActivity(), errorCode.getErrorMessage(), AppMsg.STYLE_ALERT).show();
                    }
                } catch (Exception exc) {
                    getFiles(node, true, false);
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод вызывается при добавлении файла с устройства или камеры
     *
     * @param name имя файла
     * @param path путь до файла
     */
    public void uploadFile(final String name, final String path) {
        new FileUpload(getActivity(), person, name, path) {
            @Override
            protected void onPostExecute(final String result) {
                hideProgressBar();
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        FilesAddFileTable filesAddFileTable = new FilesAddFileTable(getActivity().getBaseContext());
                        filesAddFileTable.add(FragmentFilesList.this.node.getIdentifier(), name, person.getUserName(), path, FragmentFilesList.this.node.getName());
                        getFiles(node, true, false);
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                    }
                    return;
                }
                new AsyncTask<Void, Void, String>() {
                    @Override
                    protected void onPostExecute(String result) {
                        try {
                            ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                            if (errorCode.getResult().equals(Wrapper.ERROR)) {
                                AppMsg.makeText(getActivity(), errorCode.getMessage(), AppMsg.STYLE_ALERT).show();
                            }
                        } catch (Exception exc) {
                            getFiles(node, true, false);
                        }
                        super.onPostExecute(result);
                    }
                    @Override
                    protected String doInBackground(Void... voids) {
                        return manager.newFile(node.getIdentifier(), name, result);
                    }
                }.execute();
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Добавление файла с устройства
     */
    public void fromDevice() {
        final OpenFileDialog fileDialog = new OpenFileDialog(getActivity());
        fileDialog.setOpenDialogListener(new OpenFileDialog.OpenDialogListener() {
            @Override
            public void OnSelectedFile(String path) {
                uploadFile(new File(path).getName(), path);
            }
        });
        fileDialog.show();
    }

    /**
     * Добавление файла с камеры
     *
     * @param name имя файла в миллисекундах
     */
    public void fromCamera(long name) {
        String photoPath = Utils.getNewPhotoName(name, getActivity());
        final String fileName = photoPath + Const.DEFAULT_FILE_FORMAT;
        final String filePath = Environment.getExternalStorageDirectory() + File.separator +
                Const.DIRECTORY_PHOTOS_NAME + File.separator + name + Const.DEFAULT_FILE_FORMAT;
        uploadFile(new File(fileName).getName(), filePath);
    }

    /**
     * Загрузка файла
     *
     * @param nodeID идентификатор ноды
     */
    private void getFile(String nodeID, boolean pdf) {
        if (!Utils.isOnline(getActivity().getBaseContext(), person.getHost())) {
            return;
        }
        DownloadFile downloadFile = new DownloadFile(getActivity(), person);
        downloadFile.setFileName(node.getName());
        downloadFile.setUrl(person.getHost() + "rest/api/storage/" + (pdf ? "pdf" : "file") + "/get?identifier=" + nodeID);
        downloadFile.execute();
    }

    /**
     * Загружает файлы в список
     *
     * @param node            текущая нода
     * @param showProgressBar отображать ли прогрессбар
     */
    public void getFiles(final Node node, final boolean showProgressBar, final boolean expand) {
        this.node = node;
        if (node == null) {
            progressBar.setVisibility(View.GONE);
            refreshLayout.setRefreshing(false);
            return;
        }
        new SendGetRequest("rest/api/storage/list?parentID=" + node.getIdentifier() + "&locale=" + MyApplication.getLang(), person) {
            @Override
            protected void onPreExecute() {
                if (showProgressBar) {
                    progressBar.setVisibility(View.VISIBLE);
                }
                data.clear();
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                refreshLayout.setRefreshing(false);
                if (result == null) {
                    if (Utils.checkSyncEnables(settings)) {
                        result = new FilesListTable(getActivity().getBaseContext()).get(person.getHost() +
                                "rest/api/storage/list?parentID=" + node.getIdentifier() + "&locale=" + MyApplication.getLang());
                    } else {
                        AppMsg.makeText(getActivity(), R.string.no_internet_connection, AppMsg.STYLE_ALERT).show();
                        return;
                    }
                }
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.ERROR)) {
                        data.clear();
                    }
                } catch (Exception exc) {
                    try {
                        List<Node> newFolders = new FilesNewFolderTable(getActivity().getBaseContext()).get(node.getIdentifier());
                        for (Node node : newFolders) {
                            data.add(node);
                        }
                        List<Node> newFiles = new FilesAddFileTable(getActivity().getBaseContext()).get(node.getIdentifier());
                        for (Node node : newFiles) {
                            data.add(node);
                        }
                        Collections.addAll(data, RestClient.getGson().fromJson(result, Node[].class));
                        // сортировка по алфавиту
                        Collections.sort(data, new Comparator<Node>() {
                            @Override
                            public int compare(Node node1, Node node2) {
                                return node1.getName().compareTo(node2.getName());
                            }
                        });
                        // папки должны быть над файлами
                        Collections.sort(data, 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 (expand) {
                            fragmentTree.expandNode(node.getIdentifier());
                        }
                    } catch (Exception exception) {
                        AppMsg.makeText(getActivity(), getString(R.string.no_connection), AppMsg.STYLE_ALERT).show();
                    }
                    // заполняем данными путь
                    initPath();
                }
                adapter.notifyDataSetChanged();
                super.onPostExecute(result);
            }
        }.execute();
    }

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

    /**
     * Метод скрывает/отображает компонент "Путь"
     *
     * @param hide true - скрыть, false - отобразить
     */
    public void hidePath(boolean hide) {
        if (hide) {
            view.findViewById(R.id.layout_list_view_path).setVisibility(View.INVISIBLE);
        } else {
            view.findViewById(R.id.layout_list_view_path).setVisibility(View.VISIBLE);
        }
    }

    /**
     * Метод срабатывает при натажии на кнопку "Back"
     */
    private void backPressed() {
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(Const.BACK_PRESSED_SYNC, false);
        editor.apply();
        getActivity().finish();
    }

    /**
     * Метод используется для удаления прогрессбара с экрана
     */
    public void hideProgressBar() {
        if (progressBar == null) {
            return;
        }
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public void setFragmentTree(FragmentFilesTree fragmentTree) {
        this.fragmentTree = fragmentTree;
    }

    public Node getNode() {
        return node;
    }
}