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

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.view.View;

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

import org.json.JSONObject;

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.SettingsConst;
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.documents.DocumentConst;
import kz.arta.synergy.workflow.mobile.android.documents.common.activities.DocumentInfoActivity;
import kz.arta.synergy.workflow.mobile.android.documents.common.models.DocumentItem;
import kz.arta.synergy.workflow.mobile.android.documents.resolution.activities.ResolutionActivity;
import kz.arta.synergy.workflow.mobile.android.documents.resolution.models.ItemResolutionInfo;
import kz.arta.synergy.workflow.mobile.android.documents.route.RouteManager;
import kz.arta.synergy.workflow.mobile.android.documents.route.RoutesConst;
import kz.arta.synergy.workflow.mobile.android.documents.route.activities.RouteActivity;
import kz.arta.synergy.workflow.mobile.android.documents.route.models.Routes;
import kz.arta.synergy.workflow.mobile.android.forms.general.activities.FormPlayer;
import kz.arta.synergy.workflow.mobile.android.forms.mobile.activities.FormPlayerNative;
import kz.arta.synergy.workflow.mobile.android.works.activities.WorkInfoActivity;
import kz.arta.synergy.workflow.mobile.android.works.activities.completion.CompletionWorkCommentActivity;
import kz.arta.synergy.workflow.mobile.android.works.activities.completion.CompletionWorkFileActivity;
import kz.arta.synergy.workflow.mobile.android.works.activities.send.SendWorkActivity;
import kz.arta.synergy.workflow.mobile.android.works.models.WorkItem;

/**
 * Created by neox on 27.02.15.
 * Различные утилиты связаные с работами/документами
 */
public class ActionUtils {

    /**
     * Статус завершенной работы
     */
    public static final String STATE_COMPLETION = "1";

    /**
     * На согласование
     */
    public static final String AGREEMENT = "0";

    /**
     * На рассмотрение
     */
    public static final String APPROVAL = "1";

    /**
     * На утверждение
     */
    public static final String ACQUAINTANCE = "2";

    /**
     * Перепоручение
     */
    public static final String REASSIGN = "3";

    /**
     * Константы для обновления активити
     */
    public static final int COMMENT = 1;
    public static final int PHOTO = 2;
    public static final int COMPLETION_WORK_COMMENT = 3;
    public static final int COMPLETION_WORK_FILE = 4;
    public static final int COMPLETION_WORK_FORM = 5;
    public static final int SEND_WORK = 6;
    public static final int TRANSMIT_WORK = 7;
    public static final int REJECT_WORK = 8;
    public static final int PROCESS_FINISH_INFO = 9;
    public static final int RESOLUTION = 10;
    public static final int ACTION_RESOLUTION = 11;
    public static final int SAVE_FORM = 12;
    public static final int ROUTE_START = 13;
    public static final int UPLOAD_FILE_FROM_STORAGE = 14;
    public static final int ATTACHMENT = 15;

    /**
     * Открытие активити для завершения работы с формой завершения файл
     *
     * @param activity текущее активити
     * @param person   пользователь
     * @param work     работа
     */
    public static void openActivityCompletionWorkFile(Activity activity, Person person, WorkItem work) {
        Intent intent = new Intent(activity, CompletionWorkFileActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(ActivityConst.WORK_NAME, work.getName());
        intent.putExtra(ActivityConst.WORK_ID, work.getActionID());
        activity.startActivityForResult(intent, COMPLETION_WORK_FILE);
    }

    /**
     * Открытие активити для завершения работы с формой завершения комментарий
     *
     * @param activity текущее активити
     * @param person   пользователь
     * @param work     работа
     */
    public static void openActivityCompletionWorkComment(Activity activity, Person person, WorkItem work) {
        Intent intent = new Intent(activity, CompletionWorkCommentActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(ActivityConst.WORK_NAME, work.getName());
        intent.putExtra(ActivityConst.WORK_ID, work.getActionID());
        activity.startActivityForResult(intent, COMPLETION_WORK_COMMENT);
    }

    /**
     * Метод получает идентификатор данных по форме и открывает необходимый экран для завершения работы
     *
     * @param activity текущее активити
     * @param person   пользователь
     * @param work     работа
     * @param formID   uuid формы
     */
    public static void openActivityCompletionWorkForm(final Activity activity,
                                                      final Person person,
                                                      final WorkItem work,
                                                      final String formID,
                                                      final ProgressWheel progressBar) {
        new SendGetRequest("rest/api/asforms/form/" + formID + "?locale=" + MyApplication.getLang() + "&isMobile=true", person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                if (result != null) {
                    getDataUUID(activity, person, formID, work.getActionID(), !result.equals("{}"), progressBar);
                } else {
                    AppMsg.makeText(activity, activity.getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод получает идентификатор данных по форме и открывает нужный экран для завершения работы
     *
     * @param activity текущее активити
     * @param person   пользователь
     * @param workID   работа
     * @param formID   uuid формы
     * @param isMobile используется ли мобильное представление или нет
     */
    private static void getDataUUID(final Activity activity,
                                    final Person person,
                                    final String formID,
                                    final String workID,
                                    final boolean isMobile,
                                    final ProgressWheel progressBar) {
        new SendGetRequest("rest/api/workflow/work/get_form_for_result?formUUID=" + formID +
                "&workID=" + workID + "&locale=" + MyApplication.getLang(), person) {
            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    return;
                }
                SharedPreferences settings = activity.getSharedPreferences(SettingsConst.DEFAULT_NAME_SETTINGS, Context.MODE_PRIVATE);
                float versionSynergy = settings.getFloat(SettingsConst.SYNERGY_VERSION, 0);
                if (versionSynergy < 3.7 && !isMobile) {
                    AppMsg.makeText(activity, activity.getString(R.string.mobile_definition_not_found), AppMsg.STYLE_ALERT).show();
                    return;
                }
                try {
                    JSONObject json = new JSONObject(result);
                    String dataUUID = json.getString("dataUUID");
                    String fileIdentifier = json.getString("file_identifier");
                    if (isMobile) {
                        Intent intent = new Intent(activity, FormPlayerNative.class);
                        intent.putExtra(ActivityConst.PERSON, person);
                        intent.putExtra(ActivityConst.DATA_UUID, dataUUID);
                        intent.putExtra(ActivityConst.FILE_IDENTIFIER, fileIdentifier);
                        intent.putExtra(ActivityConst.EDIT, true);
                        intent.putExtra(ActivityConst.CAN_EDIT, "true");
                        activity.startActivityForResult(intent, COMPLETION_WORK_FORM);
                    } else {
                        Intent intent = new Intent(activity, FormPlayer.class);
                        intent.putExtra(ActivityConst.PERSON, person);
                        intent.putExtra(ActivityConst.DATA_UUID, dataUUID);
                        intent.putExtra(ActivityConst.FILE_IDENTIFIER, fileIdentifier);
                        intent.putExtra(ActivityConst.EDIT, true);
                        intent.putExtra(ActivityConst.CAN_EDIT, "true");
                        activity.startActivityForResult(intent, COMPLETION_WORK_FORM);
                    }
                } catch (Exception ignored) {
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод открывает активити для отправки работы по маршруту/перепоручение
     *
     * @param activity      текущее активити
     * @param person        пользователь
     * @param work          работа
     * @param document      документ
     * @param type          тип операции (0 - согласование, 1 - ознакомление, 2 - утверждение, 3 - перепоручение)
     * @param actionType    тип действия
     * @param operationType тип операции
     */
    public static void sendWork(Activity activity, Person person, WorkItem work,
                                DocumentItem document, String type, String actionType, String operationType) {
        Intent intent = new Intent(activity, SendWorkActivity.class);
        intent.putExtra(ActivityConst.PERSON, person);
        if (work != null && work.getActionID() != null) {
            intent.putExtra(ActivityConst.WORK_ID, work.getActionID());
        } else if (document != null && document.getDocumentID() != null) {
            intent.putExtra(ActivityConst.DOCUMENT_ID, document.getDocumentID());
        }
        intent.putExtra(ActivityConst.TYPE, type);
        intent.putExtra(ActivityConst.OPERATION_TYPE, operationType);
        intent.putExtra(ActivityConst.ACTION_TYPE, actionType);
        activity.startActivityForResult(intent, ActionUtils.SEND_WORK);
    }

    /**
     * Открывает активити с информацией о работе
     *
     * @param list     список с работами
     * @param position номер открываемой работы
     * @param activity текущее активити
     * @param fragment текущий фрагмент
     * @param person   пользователь
     */
    public static void openWork(List<WorkItem> list, int position, Activity activity, Fragment fragment, Person person) {
        WorkItem workItem = list.get(position);
        Intent intent = new Intent(activity.getApplicationContext(), WorkInfoActivity.class);
        intent.putExtra(ActivityConst.WORK_ID, workItem.getActionID());
        intent.putExtra(ActivityConst.PERSON, person);
        fragment.startActivityForResult(intent, FragmentConst.UPDATE_WORK_LIST);
    }

    /**
     * Открывает активити с информацией о документе
     *
     * @param documentID uuid просматриваемого документа
     * @param activity   активити
     * @param fragment   текущий фрагмент
     * @param person     данные авторизированного пользователя
     * @param type       тип текущего фильтра
     */
    public static void openDocument(String documentID, Activity activity, Fragment fragment, Person person, String type) {
        Intent intent = new Intent(activity.getApplicationContext(), DocumentInfoActivity.class);
        intent.putExtra(ActivityConst.DOCUMENT_ID, documentID);
        intent.putExtra(ActivityConst.PERSON, person);
        intent.putExtra(DocumentConst.TYPE_ITEM_DOCUMENTS, type);
        fragment.startActivityForResult(intent, FragmentConst.UPDATE_WORK_LIST);
    }

    /**
     * Изменяет startRecord в url до списка с работами
     * Вызывается в том случае если пользователь достиг конца списка
     *
     * @param url ссылка до списка с работами
     * @param pos позиция
     * @return измененный url
     */
    public static String parseWorkUrl(String url, int pos) {
        StringBuffer str = new StringBuffer(url);
        int index1 = str.indexOf("startRecord=") + 12;
        int index2 = str.indexOf("&recordsCount");
        str = str.replace(index1, index2, String.valueOf(pos));
        return str.toString();
    }

    /**
     * Изменяет pageNumber в url до списка с документами
     * Вызывается в том случае если пользователь достиг конца списка
     *
     * @param url ссылка до списка с документами
     * @param pos позиция
     * @return измененный url
     */
    public static String parseDocumentUrl(String url, int pos) {
        StringBuffer str = new StringBuffer(url);
        int subString = str.indexOf("pageNumber=");
        str = str.replace(subString + 11, subString + 12, String.valueOf(pos));
        return str.toString();
    }

    /**
     * При открытии работы данный метод отправляет запрос на то, что работа была просмотрена пользователем
     *
     * @param workID uuid работы
     * @param person пользователь
     */
    public static void markWorkSeen(String workID, Person person) {
        new SendGetRequest("rest/api/workflow/work/set_seen?workID=" + workID + "&locale=" + MyApplication.getLang(), person) {
        }.execute();
    }

    /**
     * При открытии документа данный метод отправляет запрос на то, что документ был просмотрен пользователем
     *
     * @param documentID uuid документа
     * @param person     пользователь
     */
    public static void markDocumentSeen(String documentID, Person person) {
        new SendGetRequest("rest/api/docflow/doc/set_seen?documentID=" + documentID + "&locale=" + MyApplication.getLang(), person) {
        }.execute();
    }

    /**
     * Метод отображает диалог выбора резолюции (если больше 1)
     *
     * @param activity    текущее активити
     * @param workID      uuid работы
     * @param person      пользователь
     * @param resolutions список резолюций
     */
    public static void showResolutionDialog(final Activity activity, final String workID, final String documentID,
                                            final Person person, final List<String> resolutions) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle(activity.getString(R.string.resolution));
        builder.setItems(resolutions.toArray(new String[resolutions.size()]), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int item) {
                Intent intent = new Intent(activity, ResolutionActivity.class);
                intent.putExtra(ActivityConst.WORK_ID, workID);
                intent.putExtra(ActivityConst.DOCUMENT_ID, documentID);
                intent.putExtra(ActivityConst.PERSON, person);
                intent.putExtra(ActivityConst.WORK_INFO_RESOLUTION_ITEM, item);
                if (resolutions.get(item).equals(activity.getString(R.string.create_new_resolution))) {
                    intent.putExtra(ActivityConst.IS_NEW, true);
                }
                activity.startActivityForResult(intent, RESOLUTION);
            }
        });
        builder.setCancelable(true);
        builder.show();
    }

    /**
     * Метод смотрит на количество резолюций
     *
     * @param person      Метод проверяет количество резолюций, если больше 1 - отображает диалог, если меньше - открывает новое активити
     * @param workID      uuid работы
     * @param activity    текущее активити
     * @param progressBar прогрессбар
     */
    public static void checkSizeResolution(final Person person, final String workID, final String documentID,
                                           final Activity activity, final ProgressWheel progressBar) {
        String url;
        if (workID != null) {
            url = "rest/api/docflow/doc/get_resolution?workID=" + workID + "&locale=" +
                    MyApplication.getLang();
        } else {
            url = "rest/api/docflow/doc/get_resolution?documentID=" + documentID + "&locale=" +
                    MyApplication.getLang();
        }
        new SendGetRequest(url, person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                if (result == null) {
                    AppMsg.makeText(activity, activity.getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                    return;
                }
                ItemResolutionInfo[] resolutions;
                try {
                    resolutions = RestClient.getGson().fromJson(result, ItemResolutionInfo[].class);
                } catch (JsonSyntaxException exc) {
                    resolutions = null;
                }
                if (resolutions == null) {
                    AppMsg.makeText(activity, activity.getString(R.string.resolution_not_found), AppMsg.STYLE_ALERT).show();
                    return;
                }
                // если резолюция одна - сразу запускаем активити
                if (resolutions.length <= 1) {
                    Intent intent = new Intent(activity, ResolutionActivity.class);
                    intent.putExtra(ActivityConst.WORK_ID, workID);
                    intent.putExtra(ActivityConst.DOCUMENT_ID, documentID);
                    intent.putExtra(ActivityConst.PERSON, person);
                    activity.startActivityForResult(intent, ActionUtils.RESOLUTION);
                } else {
                    List<String> resolutionsList = new ArrayList<String>();
                    for (ItemResolutionInfo aResult : resolutions) {
                        if (aResult.getItems().length == 0) {
                            resolutionsList.add(activity.getString(R.string.create_new_resolution));
                        } else {
                            resolutionsList.add(activity.getString(R.string.resolution) + " от " + Utils.parseAuthor(aResult.getAuthor()));
                        }
                    }
                    showResolutionDialog(activity, workID, documentID, person, resolutionsList);
                }
                progressBar.setVisibility(View.GONE);
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод возвращает интент в список работ для обновления данных
     *
     * @param activity активити из которого вызывается метод
     */
    public static void updateWorkList(Activity activity) {
        Intent intent = new Intent();
        intent.putExtra(ActivityConst.UPDATE_WORK_LIST, ActivityConst.UPDATE_WORK_LIST);
        activity.setResult(Activity.RESULT_OK, intent);
        activity.finish();
    }

    /**
     * Метод получает маршрут
     *
     * @param progressBar прогрессбар
     */
    public static void getRoute(final Person person, final Activity activity,
                                final DocumentItem document, final ProgressWheel progressBar, final String type) {
        new SendGetRequest("rest/api/registry/route?registryID=" + document.getRegistryID() + "&type=" + type, person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }
            @Override
            protected void onPostExecute(String result) {
                Logger.v("RES = " + result);
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    AppMsg.makeText(activity, activity.getString(R.string.error_to_get_routes), AppMsg.STYLE_ALERT).show();
                    return;
                }
                if (result.equals("[]")) {
                    startEmptyRoute(document.getAsfDataID(), person, activity, type);
                } else {
                    try {
                        JSONObject jsonObject = new JSONObject(result);
                        String errorCode = jsonObject.getString("errorCode");
                        if (errorCode.equals("13")) {
                            AppMsg.makeText(activity, jsonObject.getString("errorMessage"), AppMsg.STYLE_ALERT).show();
                        }
                    } catch (Exception exc) {
                        Routes routes = RestClient.getGson().fromJson(result, Routes.class);
                        RouteManager routeManager = new RouteManager(routes, document, person, activity, RoutesConst.ACTIVATE);
                        if (routeManager.isShowActivity()) {
                            Intent intent = new Intent(activity, RouteActivity.class);
                            intent.putExtra(ActivityConst.PERSON, person);
                            intent.putExtra(ActivityConst.DOCUMENT, document);
                            intent.putExtra(RoutesConst.ROUTES, routes);
                            intent.putExtra(RoutesConst.ROUTE_TYPE, RoutesConst.ACTIVATE);
                            activity.startActivityForResult(intent, ActionUtils.ROUTE_START);
                        } else {
                            routeManager.startRoute(progressBar);
                        }
                    }
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    private static void startEmptyRoute(String dataUUID, Person person, final Activity activity, String type) {
        String typeUrl = "";
        switch (type) {
            case "DELETE":
                typeUrl = "delete_doc";
                break;
            case "ACTIVATE":
                typeUrl = "activate_doc";
                break;
            case "CHANGE":
                typeUrl = "modify_doc";
                break;
        }
        new SendGetRequest("rest/api/registry/" + typeUrl + "?dataUUID=" + dataUUID, person) {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }
            @Override
            protected void onPostExecute(String result) {
                if (activity instanceof DocumentInfoActivity) {
                    ((DocumentInfoActivity) activity).update();
                }
                super.onPostExecute(result);
            }
        }.execute();
    }
}
