package kz.arta.synergy.workflow.mobile.android.common.offline;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.gson.JsonSyntaxException;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import kz.arta.synergy.workflow.mobile.android.R;
import kz.arta.synergy.workflow.mobile.android.attachments.models.AttachmentItem;
import kz.arta.synergy.workflow.mobile.android.comments.CommentConst;
import kz.arta.synergy.workflow.mobile.android.comments.models.CommentItem;
import kz.arta.synergy.workflow.mobile.android.common.SettingsConst;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddAttachment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddChangeProgress;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddComment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddCompletionComment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddCompletionFile;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddEditComment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddFinishProcess;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddFormParams;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddRemoveAttachment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddRemoveComment;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddResultWork;
import kz.arta.synergy.workflow.mobile.android.common.offline.add.AddSync;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.FinishProcessTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.FormCompletionTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.LogsTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.SettingsTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorkActionsTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorkAttachmentsTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorkCommentsTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorkFiltersTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorkResultTable;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.WorksTable;
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.Const;
import kz.arta.synergy.workflow.mobile.android.common.utils.DateUtils;
import kz.arta.synergy.workflow.mobile.android.common.utils.FragmentConst;
import kz.arta.synergy.workflow.mobile.android.common.utils.Logger;
import kz.arta.synergy.workflow.mobile.android.common.utils.MyApplication;
import kz.arta.synergy.workflow.mobile.android.common.utils.Wrapper;
import kz.arta.synergy.workflow.mobile.android.documents.offline.DocumentAttachmentsTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.DocumentCommentsTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.DocumentFiltersTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.DocumentSync;
import kz.arta.synergy.workflow.mobile.android.documents.offline.DocumentTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.actions.DocumentAddAttachmentTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.actions.DocumentAddCommentTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.actions.DocumentEditCommentTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.actions.DocumentRemoveAttachmentTable;
import kz.arta.synergy.workflow.mobile.android.documents.offline.actions.DocumentRemoveCommentTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.FilesFiltersTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.FilesListTable;
import kz.arta.synergy.workflow.mobile.android.files.offline.FilesSync;
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;
import kz.arta.synergy.workflow.mobile.android.works.models.CompletionFormItem;
import kz.arta.synergy.workflow.mobile.android.works.models.CompletionResultItem;
import kz.arta.synergy.workflow.mobile.android.works.models.FilterWorkItem;
import kz.arta.synergy.workflow.mobile.android.works.models.WorkActionsItem;
import kz.arta.synergy.workflow.mobile.android.works.models.WorkItem;

/**
 * Created by neox on 04.07.14.
 * Синхронизация
 */
public class SyncMain extends AsyncTask<Void, Integer, Void> {

    private Context context;
    private Person person;
    private SharedPreferences settings;

    /**
     * Запущена ли синхронизация в данный момент
     */
    public static boolean running = false;

    /**
     * Можно ли синхронизироваться в данный момент
     */
    public static boolean canSync = true;

    /**
     * Формат даты в жунрале синхронизации
     */
    private SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.DEFAULT_DATE_JOURNAL_SYNC);

    /**
     * Положение прогрессбара
     */
    private int progressStatus;

    /**
     * Прогресс выполнения синхронизации
     */
    private ProgressBar progressBar;

    /**
     * Заголовок на прогрессбаре
     */
    private TextView progressBarTitle;

    /**
     * Отображать ли прогресс бар при синхронизации
     */
    private boolean showProgress;

    /**
     * Классы хранящие данные
     */
    private LogsTable offlineLogs;
    private WorkCommentsTable comments;
    private WorkAttachmentsTable attachments;
    private WorkActionsTable actions;
    private WorkFiltersTable filters;
    private WorksTable offlineWorks;
    private FinishProcessTable finishProcess;
    private FormCompletionTable formsCompletion;

    /**
     * Ссылки до работ (метод рекурсивно пробегается по фильтрам)
     */
    private List<Offline> urlToWorks;

    /**
     * Фильтры
     */
    private List<FilterWorkItem> filtersOffline;

    /**
     * Метод пробегается по каждой работе и складывает их сюда
     */
    private List<WorkItem> allWorks;

    /**
     * Отправка запроса на сервер и получение ответа
     */
    private SendGetRequest sendGetRequest;

    /**
     * Запущена полная или частичная синхронизация
     */
    private boolean allSync;

    /**
     * Отправлять ли данные при синхронизации
     */
    private boolean send;

    /**
     * Количество ошибок при синхронизации
     */
    private int countErrors;

    /**
     * Параметры для фильтров
     */
    private String fType;
    private String fID;
    private String oID;
    private double random;
    private String documentsKey;

    public SyncMain(Context context, Person person) {
        this.context = context;
        this.person = person;
        random = Math.random() * 1000;
        init();
    }

    public SyncMain(Context context) {
        this.context = context;
        random = Math.random() * 1000;
    }

    @Override
    protected void onCancelled() {
        running = false;
        canSync = true;
        progressBar.setProgress(allWorks.size());
    }

    /**
     * Созданание всех нужных компонентов
     */
    public void init() {

        sendGetRequest = new SendGetRequest(person);

        filtersOffline = new ArrayList<>();
        urlToWorks = new ArrayList<>();
        allWorks = new ArrayList<>();
        settings = context.getSharedPreferences(SettingsConst.DEFAULT_NAME_SETTINGS, Context.MODE_PRIVATE);

        offlineLogs = new LogsTable(context);

        filters = new WorkFiltersTable(context);
        offlineWorks = new WorksTable(context);
        comments = new WorkCommentsTable(context);

        attachments = new WorkAttachmentsTable(context);
        attachments.setPerson(person);

        actions = new WorkActionsTable(context);
        actions.setPerson(person);

        formsCompletion = new FormCompletionTable(context);
        finishProcess = new FinishProcessTable(context);
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        if (showProgress) {
            progressBar.setProgress(values[0]);
        }
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPreExecute() {
        canSync = false;
        running = true;
        if (allSync) {
            initProgressBarTitle();
        }
        super.onPreExecute();
    }

    public void initProgressBarTitle() {
        if (showProgress) {
            progressBar.setProgressDrawable(context.getResources().getDrawable(R.drawable.sync_progress_bar_active));
            progressBarTitle.setText(context.getString(R.string.sync_in_process) + "...");
        }
    }

    /**
     * Очищение всех данных в таблице
     * @param clearAll      полная очисистка
     */
    public void clearTables(boolean clearAll) {

        // общие
        if (clearAll) {

            new SettingsTable(context).removeAll();
            new LogsTable(context).removeAll();

            // работы
            new AddAttachment(context).remove();
            new AddChangeProgress(context).remove();
            new AddComment(context).remove();
            new AddCompletionComment(context).remove();
            new AddCompletionFile(context).remove();
            new AddEditComment(context).remove();
            new AddFinishProcess(context).remove();
            new AddFormParams(context).remove();
            new AddRemoveAttachment(context).remove();
            new AddRemoveComment(context).remove();
            new AddResultWork(context).remove();

            // документы
            new DocumentAddAttachmentTable(context).removeAll();
            new DocumentAddCommentTable(context).removeAll();
            new DocumentEditCommentTable(context).removeAll();
            new DocumentRemoveAttachmentTable(context).removeAll();
            new DocumentRemoveCommentTable(context).removeAll();
            new DocumentRemoveCommentTable(context).removeAll();

            // файлы
            new FilesAddFileTable(context).removeAll();
            new FilesMoveTable(context).removeAll();
            new FilesNewFolderTable(context).removeAll();
            new FilesRemoveTable(context).removeAll();
            new FilesRenameTable(context).removeAll();

        }

        // работы
        new WorkFiltersTable(context).removeAll();
        new WorksTable(context).removeAll();
        new WorkActionsTable(context).removeAll();
        new WorkAttachmentsTable(context).removeAll();
        new WorkCommentsTable(context).removeAll();
        new FinishProcessTable(context).removeAll();
        new FormCompletionTable(context).removeAll();
        new WorkResultTable(context).removeAll();

        // документы
        new DocumentAttachmentsTable(context).removeAll();
        new DocumentCommentsTable(context).removeAll();
        new DocumentFiltersTable(context).removeAll();
        new DocumentTable(context).removeAll();

        // файлы
        new FilesFiltersTable(context).removeAll();
        new FilesListTable(context).removeAll();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        canSync = true;
        running = false;
        if (!allSync) {
            return;
        }
        if (countErrors > 0) {
            if (showProgress) {
                progressBar.setProgress(0);
                if (settings.contains(Const.SYNC_DATA) && !settings.getString(Const.SYNC_DATA, "").equals(context.getString(R.string.start_sync))) {
                    progressBarTitle.setText("Последняя синхронизация: " + settings.getString(Const.SYNC_DATA, ""));
                } else {
                    progressBarTitle.setText(context.getString(R.string.start_sync));
                }
            }
        } else {
            // получаем текущую дату
            String date = DateUtils.getDateLabelSync(context);
            // обновляем прогресс если надо
            if (showProgress) {
                // позицию прогрессбара выставляем 0
                progressBar.setProgress(0);
                // в заголовок прогрессбара выставляем дату последней сихронизации
                progressBarTitle.setText("Последняя синхронизация: " + date);
            }
            // сохраняем дату последней синхронизации
            SharedPreferences.Editor editor = settings.edit();
            editor.putString(Const.SYNC_DATA, date);
            editor.apply();
        }
        if (showProgress) {
            Drawable progressDrawable = context.getResources().getDrawable(R.drawable.sync_progress_bar);
            progressBar.setProgressDrawable(progressDrawable);
        }
        super.onPostExecute(aVoid);
    }

    @Override
    protected Void doInBackground(Void... voids) {
        // если allSync == true - значит запускаем полную синхронизацию
        // иначе - обычную
        if (allSync) {
            // отправляем данные
            if (send) {
                AddSync addSync = new AddSync(context, person);
                addSync.start();
                addSync.clear();
            }
            // получаем данные
            getAllSync();
        } else {
            if (documentsKey != null) {
                getDocumentsSync();
            } else {
                getListSync();
            }
        }
        return null;
    }

    /**
     * Метод для неполной синхронизации
     * Берет работы из массива allWorks и загружает данные по ним
     */
    private void getListSync() {

        offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_started),
                sdf.format(System.currentTimeMillis()), random + "");

        offlineWorks.removeWorksByArray(fType, fID, oID);
        comments.removeWorksByArray(allWorks);
        attachments.removeWorksByArray(allWorks);
        actions.removeWorksByArray(allWorks);
        formsCompletion.removeWorksByArray(allWorks);

        for (WorkItem allWork : allWorks) {
            allWork.setFilterType(fType);
            allWork.setFilterID(fID);
            allWork.setObjectID(oID);
        }

        offlineWorks.addWorksInTable(allWorks);

        // загружаем всю информацию о работах и обновляем прогрессбар
        for (WorkItem work : allWorks) {
            try {
                getWorkDetails(work);
            } catch (Exception exc) {
                countErrors++;
                offlineLogs.add("2", "Работа " + "\"" + work.getName() + "\":" + " ошибка синхронизации",
                        sdf.format(System.currentTimeMillis()), random + "");
            }
        }

        if (countErrors > 0) {
            offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_finished_error),
                    sdf.format(System.currentTimeMillis()), random + "");
        } else {
            offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_finished_successful),
                    sdf.format(System.currentTimeMillis()), random + "");
        }
    }

    private void getDocumentsSync() {
        String key = person.getHost() + documentsKey;
        DocumentSync documentSync = new DocumentSync(person, context, false, random);
        documentSync.listSync(key);
    }

    /**
     * Метод для полной синхронизации
     * Рекурсивно загружает фильтры
     * Получает ссылки к каждому фильтру
     * Отправляет запрос на получения работ для каждого фильтра
     * Пишет данные в базу данных
     */
    private void getAllSync() {

        offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_started),
                sdf.format(System.currentTimeMillis()), random + "");

        // настройки приложения
        String settings = sendGetRequest.requestGET(person.getHost() + "rest/api/settings/get");
        if (settings != null) {
            SettingsTable settingsTable = new SettingsTable(context);
            settingsTable.removeAll();
            settingsTable.insert(settings);
        } else {
            countErrors++;
        }

        // рекурсивно загружаем фильтры
        getWorkFilters(person.getHost() + "rest/api/workflow/works/filters/" +
                person.getUuid() + "?getCounters=true&locale=" + MyApplication.getLang(), 0);

        // пробегаемся по всем фильтрам и получаем урлы до работ
        for (FilterWorkItem aFiltersOffline : filtersOffline) {
            String url = null;
            if (aFiltersOffline.getLevel() == 0) {
                url = person.getHost() + "rest/api/workflow/works/list/" +
                        person.getUuid() + "?filterType=" + aFiltersOffline.getFilterType() +
                        "&startRecord=0&recordsCount=" + "999" + "&locale=" + MyApplication.getLang();
            } else {
                if (aFiltersOffline.getFilterID() != null) {
                    url = person.getHost() + "rest/api/workflow/works/list/" +
                            person.getUuid() + "?filterType=" + aFiltersOffline.getFilterType() +
                            "&filterID=" + aFiltersOffline.getFilterID() +
                            "&startRecord=0&recordsCount=" + FragmentConst.DEFAULT_COUNT_WORKS + "&locale=" + MyApplication.getLang();
                } else if (aFiltersOffline.getObjectID() != null) {
                    url = person.getHost() + "rest/api/workflow/works/list/" +
                            person.getUuid() + "?filterType=" + aFiltersOffline.getFilterType() +
                            "&objectID=" + aFiltersOffline.getObjectID() +
                            "&startRecord=0&recordsCount=" + FragmentConst.DEFAULT_COUNT_WORKS + "&locale=" + MyApplication.getLang();
                }
            }
            // добавляем их в массив
            // также добавляем данные по фильтрам, чтобы знать какому фильтру принадлежит работа
            urlToWorks.add(new Offline(url, aFiltersOffline.getFilterType(),
                    aFiltersOffline.getFilterID(), aFiltersOffline.getObjectID(), aFiltersOffline.getName()));
        }

        // загружаем информацию о работах
        getWorkDetails();

        // синхронизируем документы
        DocumentSync documentsSync = new DocumentSync(person, context, true, random);
        documentsSync.allSync();

        // синхронизируем файлы
        FilesSync filesSync = new FilesSync(person, context, random);
        filesSync.allSync();

        if (countErrors > 0) {
            offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_finished_error),
                    sdf.format(System.currentTimeMillis()), random + "");
        } else {
            offlineLogs.add(Wrapper.NO_ERROR, context.getString(R.string.sync_finished_successful),
                    sdf.format(System.currentTimeMillis()), random + "");
        }
    }

    /**
     * Метод пробегается по всем ссылкам и пишет данные в базу данных
     * Параллельно обновляя прогрессбар
     */
    private void getWorkDetails() {

        // пробегаемся по всем ссылкам и получаем работы
        // складываем их базу данных
        for (Offline url : urlToWorks) {

            // получаем строку в формате json
            String result = sendGetRequest.requestGET(url.url);

            // пытаемся распарсить
            try {
                WorkItem[] works = RestClient.getGson().fromJson(result, WorkItem[].class);
                for (WorkItem work : works) {
                    work.setFilterType(url.filterType);
                    work.setFilterID(url.filterID);
                    work.setObjectID(url.objectID);
                    work.setFilterName(url.filterName);
                    allWorks.add(work);
                }
            } catch (JsonSyntaxException exc) {
                countErrors++;
                return;
            }
        }

        if (showProgress) {
            // выставляем максимльное положение прогрессбара
            progressBar.setMax(allWorks.size());
        }

        // и добавляем все работы в базу
        offlineWorks.addWorksInTable(allWorks);

        // загружаем всю информацию о работах и обновляем прогресс
        for (WorkItem work : allWorks) {
            progressStatus++;
            publishProgress(progressStatus);
            if (running && countErrors < 5) {
                try {
                    getWorkDetails(work);
                } catch (Exception exc) {
                    countErrors++;
                    offlineLogs.add("2", "Работа " + "\"" + work.getName() + "\":" + " ошибка синхронизации",
                            sdf.format(System.currentTimeMillis()), random + "");
                }
            } else {
                onCancelled();
                cancel(true);
            }
        }
    }

    /**
     * Метод загружает для каждой работы комментарии/вложения/действия/формы завершения и добавляет их в базу данных
     *
     * @param work - объект "работа"
     */
    private void getWorkDetails(WorkItem work) throws Exception {

        // если у нас уже есть текущая работа в списке - выходим из метода
        List<CommentItem> commentsList = comments.getByWorkID(work.getActionID());
        if (!commentsList.isEmpty()) {
            return;
        }

        List<AttachmentItem> attachmentsList = attachments.get(work.getActionID());
        if (!attachmentsList.isEmpty()) {
            return;
        }

        List<WorkActionsItem> actionsList = actions.get(work.getActionID());
        if (!actionsList.isEmpty()) {
            return;
        }

        CompletionResultItem fCompletion = formsCompletion.getByWorkId(work.getActionID());
        if (fCompletion != null && fCompletion.getActionID() != null) {
            return;
        }

        // комментарии к работе
        String commentsStr = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/" +
                work.getActionID() + "/comments?count=999" + "&locale=" + MyApplication.getLang() + "&type=" + CommentConst.WORK);
        comments.add(commentsStr, CommentConst.WORK, work.getActionID());

        // комментарии к документу
        commentsStr = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/" +
                work.getActionID() + "/comments?count=999" + "&locale=" + MyApplication.getLang() + "&type=" + CommentConst.DOCUMENT);
        comments.add(commentsStr, CommentConst.DOCUMENT, work.getActionID());

        // личные
        commentsStr = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/" +
                work.getActionID() + "/comments?count=999" + "&locale=" + MyApplication.getLang() + "&type=" + CommentConst.PERSONAL);
        comments.add(commentsStr, CommentConst.PERSONAL, work.getActionID());

        // вложения
        String attachmentsStr = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/" +
                work.getActionID() + "/attachments?count=999" + "&locale=" + MyApplication.getLang());
        attachments.add(attachmentsStr, work.getActionID());

        // действия с работой
        String actionsStr = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work_actions?workID=" +
                work.getActionID() + "&locale=" + MyApplication.getLang());
        actions.add(actionsStr, work.getActionID());

        // формы завершения
        String formCompletion = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/completion_result?workID=" +
                work.getActionID() + "&locale=" + MyApplication.getLang());

        CompletionResultItem completionResultItem;
        try {
            completionResultItem = RestClient.getGson().fromJson(formCompletion, CompletionResultItem.class);
        } catch (JsonSyntaxException exc) {
            completionResultItem = null;
        }

        // если работа завершена с какой либо формой завершения
        if (completionResultItem != null) {
            formsCompletion.addFormCompletion(completionResultItem, work.getActionID());
        } else {
            String formType = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/work/get_completion_data?workID=" +
                    work.getActionID() + "&locale=" + MyApplication.getLang());
            CompletionFormItem completionFormItem = RestClient.getGson().fromJson(formType, CompletionFormItem.class);
            if (completionFormItem.getErrorCode() == null) {
                formsCompletion.addFormType(completionFormItem, work.getActionID());
            }
        }

        // завершение работы
        if ((work.getWork_state_label().equals("agreement") && work.getWork_state_icon().equals("progress_mfa_icon")) ||
                (work.getWork_state_label().equals("approval") && work.getWork_state_icon().equals("progress_mfa_icon")) ||
                    (work.getWork_state_label().equals("acquaintance") && work.getWork_state_icon().equals("progress_mfa_icon"))) {
            String process = sendGetRequest.requestGET(person.getHost() + "rest/api/workflow/process_info?workID=" + work.getActionID() + "&locale=" + MyApplication.getLang());
            finishProcess.add(process, work.getActionID());
        }

        offlineLogs.add("1", "Работа " + "\"" + work.getName() + "\"" + " успешно синхронизирована",
                sdf.format(System.currentTimeMillis()), random + "");
    }


    /**
     * Метод рекурсивно пробегается по фильтрам - собирает их в один массив
     *
     * @param urlToServer - урл до сервера
     * @param level       - уровень вложенности
     */
    public void getWorkFilters(String urlToServer, int level) {
        // получаем корневые фильтры
        String mainFilters = new SendGetRequest(person).requestGET(urlToServer);
        Logger.v("filters str = " + mainFilters);
        // добавляем фильтры в базу данных
        filters.put(urlToServer, mainFilters);
        FilterWorkItem[] filters = null;
        try {
            filters = RestClient.getGson().fromJson(mainFilters, FilterWorkItem[].class);
        } catch (JsonSyntaxException exc) {
            // handling error
        }
        if (filters != null) {
            for (FilterWorkItem filter : filters) {
                filter.setLevel(level);
                filtersOffline.add(filter);
                if (filter.getHasChildren().equals("true")) {
                    String url = "rest/api/workflow/works/filters/" + person.getUuid() +
                            "?filterType=" + filter.getFilterType() + "&getCounters=true&locale=" + MyApplication.getLang();
                    if (filter.getFilterID() != null && !filter.getFilterID().isEmpty()) {
                        url = url + "&parentID=" + filter.getFilterID();
                    }
                    if (filter.getObjectID() != null && !filter.getObjectID().isEmpty()) {
                        url = url + "&parentObjectID=" + filter.getObjectID();
                    }
                    getWorkFilters(person.getHost() + url, level + 1);
                }
            }
        }
    }

    public void setSend(boolean send) {
        this.send = send;
    }

    public void setfType(String fType) {
        this.fType = fType;
    }

    public void setfID(String fID) {
        this.fID = fID;
    }

    public void setoID(String oID) {
        this.oID = oID;
    }

    public void setAllWorks(List<WorkItem> allWorks) {
        this.allWorks = allWorks;
    }

    public void setAllSync(boolean allSync) {
        this.allSync = allSync;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public void setProgressBar(ProgressBar progressBar) {
        this.progressBar = progressBar;
    }

    public void setProgressBarTitle(TextView progressBarTitle) {
        this.progressBarTitle = progressBarTitle;
    }

    public void setShowProgress(boolean showProgress) {
        this.showProgress = showProgress;
    }

    public void setDocumentsKey(String documentsKey) {
        this.documentsKey = documentsKey;
    }

    class Offline {

        String url;
        String filterType;
        String filterID;
        String objectID;
        String filterName;

        Offline(String url, String filterType, String filterID, String objectID, String filterName) {
            this.url = url;
            this.filterType = filterType;
            this.filterID = filterID;
            this.objectID = objectID;
            this.filterName = filterName;
        }
    }
}
