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

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;

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

import java.io.Serializable;
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.components.SearchEditText;
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.Wrapper;
import kz.arta.synergy.workflow.mobile.android.files.FilesConst;
import kz.arta.synergy.workflow.mobile.android.files.adapters.AdapterSearchFiles;
import kz.arta.synergy.workflow.mobile.android.files.manager.DownloadFile;
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.manager.SearchParams;
import kz.arta.synergy.workflow.mobile.android.files.models.Node;
import kz.arta.synergy.workflow.mobile.android.files.models.SearchFiles;
import kz.arta.synergy.workflow.mobile.android.files.models.SearchNode;

/**
 * Created by neox on 27.10.15.
 * Экран используется для поиска файлов
 */
public class SearchFilesActivity extends Activity {

    /**
     * onActivityResult
     */
    private static final int SEARCH_PARAMS = 1;

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

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

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

    /**
     * Нода в которой производится поиск
     */
    private Node node;

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

    /**
     * Адаптер списка
     */
    private BaseAdapter adapter;

    /**
     * Менеджер для работы с запросами
     */
    private FilesManager manager;

    /**
     * Параметры поиска
     */
    private SearchParams params;

    /**
     * Для динамического добавления работ при скорллинге
     */
    private boolean isLoading = false;

    /**
     * Номер первого файла
     */
    private int firstResult = 0;

    /**
     * Новые параметры
     */
    private boolean newParams;

    /**
     * Количество файлов при поиске для каждого из типа файлов
     */
    private List<Integer> fileTypesCount;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.files_search_activity);

        activity = this;

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

        Intent intent = getIntent();
        person = (Person) intent.getSerializableExtra(ActivityConst.PERSON);
        node = (Node) intent.getSerializableExtra(FilesConst.NODE);

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

        init();
        getFiles(true, true);
    }

    /**
     * Инициализация компоненов
     */
    private void init() {
        // параметры поиска
        params = new SearchParams();
        // идентификатор папки в которой производится поиск
        if (node.getIdentifier() != null) {
            params.setFolderID(node.getIdentifier());
        }
        // менеджер
        manager = new FilesManager(person);
        // данные
        data = new ArrayList<>();
        // адаптер
        adapter = new AdapterSearchFiles(activity, data, person);
        // список
        ListView list = (ListView) findViewById(R.id.files_search_list);
        // связываем адаптер и список
        list.setAdapter(adapter);
        // лонг тап
        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {
                showDialog(data.get(position).getIdentifier());
                return true;
            }
        });
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                // право на загрузку
                if (FilesRights.checkRight(data.get(position).getRight(), FilesRights.LOAD_DOCUMENT)) {
                    // загружаем файл на устройство и открываем
                    getFile(data.get(position).getIdentifier());
                }
            }
        });
        // скроллинг
        list.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (totalItemCount >= SearchParams.COUNT_FILES) {
                    final int lastItem = firstVisibleItem + visibleItemCount;
                    if (lastItem == totalItemCount) {
                        if (!isLoading) {
                            isLoading = true;
                            firstResult = firstResult + SearchParams.COUNT_FILES;
                            params.setFirstResult(firstResult);
                            getFiles(true, false);
                        }
                    }
                }
            }

            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {
            }

        });

        // компонент для поиска
        final SearchEditText searchEdit = (SearchEditText) findViewById(R.id.files_search_search_text);
        searchEdit.setListener(new SearchEditText.SearchTextListener() {
            @Override
            public void onTextChanged(String text) {
                newParams = !searchEdit.getText().equals(params.getContains());
                params.setContains(text);
                params.setFolderID(node.getIdentifier());
                getFiles(true, true);
            }
        });

        // кнопка для открытия настроек поиска
        RelativeLayout button = (RelativeLayout) findViewById(R.id.files_search_search_layout);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (fileTypesCount.size() == 5 && fileTypesCount.get(0) == 0 && fileTypesCount.get(1) == 0 && fileTypesCount.get(2) == 0
                        && fileTypesCount.get(3) == 0 && fileTypesCount.get(4) == 0 && params.getModifiedTo() == null && params.getModifiedFrom() == null) {
                    return;
                }
                if (newParams) {
                    params = new SearchParams();
                    params.setContains(searchEdit.getText());
                    params.setFolderID(node.getIdentifier());
                }
                Intent intent = new Intent(activity, SearchParamsActivity.class);
                intent.putExtra(FilesConst.SEARCH_PARAMS, params);
                intent.putExtra(FilesConst.FILES_TYPES_COUNT, (Serializable) fileTypesCount);
                startActivityForResult(intent, SEARCH_PARAMS);
            }
        });
    }

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

    /**
     * Метод используется для отображения диалога, который происходит при долгом тапе по плашке
     */
    private void showDialog(final String nodeID) {
        String[] items = {getString(R.string.go_to_folder)};
        AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
        dialog.setTitle(getString(R.string.actions));
        dialog.setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, final int pos) {
                switch (pos) {
                    case 0: {
                        goToFolder(nodeID);
                    }
                    break;
                }
            }
        });
        dialog.setCancelable(true);
        dialog.show();
    }

    /**
     * Метод вызывается при нажатии на контекстное меню "Перейти к папке"
     */
    private void goToFolder(String nodeID) {
        new SendGetRequest("rest/api/storage/description?elementID=" + nodeID, person) {
            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    AppMsg.makeText(activity, activity.getString(R.string.error_to_get_node_description), AppMsg.STYLE_ALERT).show();
                    return;
                }
                try {
                    Node node = RestClient.getGson().fromJson(result, Node.class);
                    Intent intent = new Intent();
                    intent.putExtra(FilesConst.NODE, node);
                    setResult(RESULT_OK, intent);
                    finish();
                } catch (Exception exc) {
                    AppMsg.makeText(activity, activity.getString(R.string.error_to_get_node_description), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод используется для поиска файлов
     *
     * @param showProgressBar отображать ли прогрессбар при поиске
     * @param newList         используется ли обновление списка полностью
     */
    private void getFiles(final boolean showProgressBar, final boolean newList) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected void onPreExecute() {
                if (showProgressBar) {
                    progressBar.setVisibility(View.VISIBLE);
                }
                if (newList) {
                    data.clear();
                    firstResult = 0;
                    params.setFirstResult(firstResult);
                }
                super.onPreExecute();
            }

            @Override
            protected String doInBackground(Void... voids) {

                if (newList) {

                    fileTypesCount = new ArrayList<>();
                    String aiType = params.getAiType();
                    SearchFiles searchFiles;

                    params.setAiType(FilesConst.AI_DOCUMENT);
                    searchFiles = RestClient.getGson().fromJson(manager.search(params), SearchFiles.class);
                    fileTypesCount.add(Integer.parseInt(searchFiles.getCount()));

                    params.setAiType(FilesConst.AI_IMAGE);
                    searchFiles = RestClient.getGson().fromJson(manager.search(params), SearchFiles.class);
                    fileTypesCount.add(Integer.parseInt(searchFiles.getCount()));

                    params.setAiType(FilesConst.AI_VIDEO);
                    searchFiles = RestClient.getGson().fromJson(manager.search(params), SearchFiles.class);
                    fileTypesCount.add(Integer.parseInt(searchFiles.getCount()));

                    params.setAiType(FilesConst.AI_AUDIO);
                    searchFiles = RestClient.getGson().fromJson(manager.search(params), SearchFiles.class);
                    fileTypesCount.add(Integer.parseInt(searchFiles.getCount()));

                    params.setAiType(FilesConst.AI_APPLICATION);
                    searchFiles = RestClient.getGson().fromJson(manager.search(params), SearchFiles.class);
                    fileTypesCount.add(Integer.parseInt(searchFiles.getCount()));

                    params.setAiType(aiType);
                }

                return manager.search(params);
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                try {
                    ErrorCode errorCode = RestClient.getGson().fromJson(result, ErrorCode.class);
                    if (errorCode.getErrorCode().equals(Wrapper.ERROR)) {
                        data.clear();
                    }
                } catch (Exception exc) {
                    try {
                        SearchFiles searchFiles = RestClient.getGson().fromJson(result, SearchFiles.class);
                        for (SearchNode node : searchFiles.getList()) {
                            data.add(node);
                        }
                        isLoading = searchFiles.getList().isEmpty();
                    } catch (Exception exception) {
                        AppMsg.makeText(activity, getString(R.string.error_to_get_files), AppMsg.STYLE_ALERT).show();
                    }
                }
                adapter.notifyDataSetChanged();
                super.onPostExecute(result);
            }
        }.execute();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }
        if (requestCode == SEARCH_PARAMS) {
            params = (SearchParams) data.getSerializableExtra(FilesConst.SEARCH_PARAMS);
            getFiles(true, true);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

}
