package kz.arta.synergy.workflow.mobile.android.works.activities.completion.process;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

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

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.components.AButton;
import kz.arta.synergy.workflow.mobile.android.common.components.ACheckBox;
import kz.arta.synergy.workflow.mobile.android.common.components.OpenFileDialog;
import kz.arta.synergy.workflow.mobile.android.common.models.Person;
import kz.arta.synergy.workflow.mobile.android.common.offline.get.FinishProcessTable;
import kz.arta.synergy.workflow.mobile.android.common.requests.RestClient;
import kz.arta.synergy.workflow.mobile.android.common.requests.SendGetRequest;
import kz.arta.synergy.workflow.mobile.android.common.utils.Fonts;
import kz.arta.synergy.workflow.mobile.android.common.utils.MyApplication;
import kz.arta.synergy.workflow.mobile.android.common.utils.Utils;
import kz.arta.synergy.workflow.mobile.android.documents.common.models.DocumentItem;
import kz.arta.synergy.workflow.mobile.android.works.manager.completion.FinishProcess;
import kz.arta.synergy.workflow.mobile.android.works.manager.completion.SignManager;
import kz.arta.synergy.workflow.mobile.android.works.models.ScreenFinishInfoItem;

/**
 * Created by neox on 21.04.14.
 * Экран для завершения работы процессом (согласование/утверждение/ознакомление)
 */
public class FinishProcessActivity extends Activity {

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

    /**
     * UUID работы
     */
    private String workID;

    /**
     * Идентификатор документа
     */
    private String documentID;

    /**
     * Имя работы
     */
    private String name;

    /**
     * Идентификатор процесса
     */
    private String procInstID;

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

    /**
     * Текст комментария
     */
    private EditText commentText;

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

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

    /**
     * Чекбокс "Добавить подпись"
     */
    private ACheckBox addSignature;

    /**
     * Чекбокс "Использовать ЭЦП"
     */
    private ACheckBox addEDS;

    /**
     * Кнопка "Информация о ЭЦП"
     */
    private TextView informationButton;

    /**
     * Путь до файла с ЭЦП
     */
    private String pathToCert;

    /**
     * Пароль для текущей ЭЦП
     */
    private String password;

    /**
     * Данные которые будут подписываться
     */
    private String rawData;

    /**
     * Идентификатор сертификата
     */
    private String certID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.process_finish_info_activity);

        activity = this;

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.hide();
            ((TextView) findViewById(R.id.title_action_bar_process_finish)).setTypeface(Fonts.getMedium(activity));
        }

        settings = getSharedPreferences(SettingsConst.DEFAULT_NAME_SETTINGS, Context.MODE_PRIVATE);

        // здесь хранится путь до файла ЭЦП
        pathToCert = settings.getString(ProcessConst.CERT_PATH, "");

        // получаем интент
        Intent intent = getIntent();
        person = (Person) intent.getSerializableExtra(ActivityConst.PERSON);
        documentID = intent.getStringExtra(ActivityConst.DOCUMENT_ID);
        workID = intent.getStringExtra(ActivityConst.WORK_ID);
        procInstID = intent.getStringExtra(ActivityConst.PROC_INST_ID);
        name = intent.getStringExtra(ActivityConst.WORK_NAME);

        // если подписывается документ через работу
        if (documentID == null) {
            // переключатель "Добавить подпись"
            addSignature = (ACheckBox) findViewById(R.id.add_signature_check_box);
            addSignature.setText(getResources().getString(R.string.add_signature));
            addSignature.addTextBoxListener(new ACheckBox.CheckBoxListener() {
                @Override
                public void changeState(boolean state) {
                    if (state) {
                        // если доступно подписание документов на сервере
                        if (person.getSettings().isEnableEDS()) {
                            addEDS.setEnabled(true);
                        }
                        if (person.getSettings().isNeedCert()) {
                            addEDS.setEnabled(false);
                            addEDS.setValue(true);
                        }
                    } else {
                        // если выключен переключатель "Подписать" - переключатель связанный с ЭЦП должен быть недоступен и неактивен
                        addEDS.setValue(false);
                        addEDS.setEnabled(false);
                    }
                }
            });
        } else {
            addSignature = (ACheckBox) findViewById(R.id.add_signature_check_box);
            addSignature.setVisibility(View.GONE);
        }

        // переключатель "Использовать ЭЦП"
        addEDS = (ACheckBox) findViewById(R.id.add_eds_check_box);
        addEDS.setText(getResources().getString(R.string.add_eds));
        addEDS.setEnabled(false);
        addEDS.addTextBoxListener(new ACheckBox.CheckBoxListener() {
            @Override
            public void changeState(boolean state) {
                if (!state) {
                    informationButton.setVisibility(View.GONE);
                    password = null;
                    pathToCert = null;
                }
                if (documentID == null) {
                    new BuildActivity(false).execute();
                } else {
                    initSignDocumentComponents();
                }
            }
        });

        // кнопка для перехода в информацию о файле ЭЦП
        informationButton = (TextView) findViewById(R.id.process_finish_info_cert_information_button);
        informationButton.setTypeface(Fonts.getRoman(activity));
        informationButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openCertInfoActivity(pathToCert, password);
            }
        });

        // компонент для ввода комментария
        commentText = (EditText) findViewById(R.id.process_finish_info_text_comment);

        // прогрессбар
        progressBar = (ProgressWheel) findViewById(R.id.finish_process_progress_bar);

        if (documentID == null) {
            new BuildActivity(true).execute();
        } else {
            getDocument();
        }
    }

    /**
     * Инициализация компонентов для подписи документа
     */
    private void initSignDocumentComponents() {
        // компонент для ввода комментария не нужен
        commentText.setVisibility(View.GONE);
        // прогрессбар не нужен
        progressBar.setVisibility(View.GONE);
        // требовать ли сертификат при подписи
        if (person.getSettings().isEnableEDS()) {
            addEDS.setEnabled(true);
        }
        if (person.getSettings().isNeedCert()) {
            addEDS.setValue(true);
            addEDS.setEnabled(false);
        }
        // контейнер для кнопок
        LinearLayout actions = (LinearLayout) findViewById(R.id.process_finish_info_buttons);
        actions.removeAllViews();
        if (password == null || password.isEmpty()) {
            // кнопка отображающая диалог выбора файла эцп
            AButton showSignDialog = new AButton(activity);
            if (addEDS.getValue()) {
                showSignDialog.setText("Выбрать ЭЦП");
            } else {
                showSignDialog.setText("Подписать");
            }
            showSignDialog.setBackground(AButton.GREEN);
            showSignDialog.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (rawData == null) {
                        AppMsg.makeText(activity, "Данная функция недоступна, т.к. используется версия ARTA Synergy ниже 3.6", AppMsg.STYLE_ALERT).show();
                        return;
                    }
                    if (addEDS.getValue()) {
                        signButtonTap();
                    } else {
                        signDocument();
                    }
                }
            });
            actions.addView(showSignDialog);
        } else {
            informationButton.setVisibility(View.VISIBLE);
            // кнопка отображающая диалог выбора файла эцп
            AButton signButton = new AButton(activity);
            signButton.setText(R.string.subscribe);
            signButton.setBackground(AButton.GREEN);
            signButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (rawData == null) {
                        AppMsg.makeText(activity, "Данная функция недоступна, т.к. используется версия ARTA Synergy ниже 3.6", AppMsg.STYLE_ALERT).show();
                        return;
                    }
                    signDocument();
                }
            });
            actions.addView(signButton);
            // кнопка изменяющая файл эцп
            AButton action = new AButton(activity);
            action.setText(R.string.change_eds);
            action.setBackground(AButton.GRAY);
            action.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    changeSignButtonTap();
                }
            });
            actions.addView(action);
        }
        findViewById(R.id.finish_process_general_components).setVisibility(View.VISIBLE);
        actions.setVisibility(View.VISIBLE);
    }

    /**
     * Нажатие на кнопку "Подписать"
     */
    private void signButtonTap() {
        if (settings.getString(ProcessConst.CERT_PATH, "").isEmpty()) {
            final OpenFileDialog fileDialog = new OpenFileDialog(activity);
            fileDialog.setFilter(ProcessConst.FILTER);
            fileDialog.setOpenDialogListener(new OpenFileDialog.OpenDialogListener() {
                @Override
                public void OnSelectedFile(String filePath) {
                    openCertPasswordActivity(filePath);
                }
            });
            fileDialog.setButtonPressedListener(new OpenFileDialog.OnButtonPressedListener() {
                @Override
                public void onOkPressed() {
                    AppMsg.makeText(activity, getString(R.string.file_not_selected), AppMsg.STYLE_ALERT).show();
                }

                @Override
                public void onCancelPressed() {
                }
            });
            fileDialog.show().getWindow().setLayout(Utils.dpToPx(ProcessConst.DIALOG_WIDTH, activity),
                    Utils.dpToPx(ProcessConst.DIALOG_HEIGHT, activity));
        } else {
            openCertPasswordActivity(settings.getString(ProcessConst.CERT_PATH, ""));
        }
    }

    /**
     * Нажатие на кнопку "Изменить ЭЦП"
     */
    private void changeSignButtonTap() {
        password = null;
        certID = null;
        pathToCert = null;
        informationButton.setVisibility(View.GONE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(ProcessConst.CERT_PATH, "");
        editor.apply();
        final OpenFileDialog fileDialog = new OpenFileDialog(activity);
        fileDialog.setFilter(ProcessConst.FILTER);
        fileDialog.setOpenDialogListener(new OpenFileDialog.OpenDialogListener() {
            @Override
            public void OnSelectedFile(String filePath) {
                openCertPasswordActivity(filePath);
            }
        });
        fileDialog.setButtonPressedListener(new OpenFileDialog.OnButtonPressedListener() {
            @Override
            public void onOkPressed() {
                AppMsg.makeText(activity, getString(R.string.file_not_selected), AppMsg.STYLE_ALERT).show();
            }

            @Override
            public void onCancelPressed() {
            }
        });
        fileDialog.show().getWindow().setLayout(Utils.dpToPx(ProcessConst.DIALOG_WIDTH, activity),
                Utils.dpToPx(ProcessConst.DIALOG_HEIGHT, activity));
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != ProcessConst.CERT_PASSWORD_ACTIVITY) {
            return;
        }
        if (resultCode != Activity.RESULT_OK) {
            return;
        }
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(ProcessConst.CERT_PATH, data.getStringExtra(ProcessConst.CERT_PATH));
        editor.apply();
        password = data.getStringExtra(ProcessConst.CERT_PASSWORD);
        certID = data.getStringExtra(ProcessConst.CERT_ID);
        pathToCert = data.getStringExtra(ProcessConst.CERT_PATH);
        if (documentID == null) {
            new BuildActivity(true).execute();
        } else {
            initSignDocumentComponents();
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Метод используется для открытия экрана ввода пароля
     *
     * @param filePath путь до сертификата
     */
    private void openCertPasswordActivity(String filePath) {
        Intent intent = new Intent(activity, CertPasswordActivity.class);
        intent.putExtra(ProcessConst.CERT_PATH, filePath);
        intent.putExtra(ActivityConst.PERSON, person);
        startActivityForResult(intent, ProcessConst.CERT_PASSWORD_ACTIVITY);
    }

    /**
     * Метод используется для открытия экрана информации о ЭЦП
     *
     * @param filePath путь до сертификата
     * @param password пароль к сертификату
     */
    private void openCertInfoActivity(String filePath, String password) {
        Intent intent = new Intent(activity, CertInfoActivity.class);
        intent.putExtra(ProcessConst.CERT_PATH, filePath);
        intent.putExtra(ProcessConst.CERT_PASSWORD, password);
        startActivity(intent);
    }

    /**
     * Метод используется для добавления кнопки на layout
     *
     * @param button              описание кнопки
     * @param needPositiveComment необходимо ли вводить позитивный комментарий при завершении
     * @param needNegativeComment необходимо ли вводить негативынй комментарий при завершении
     * @param actions             layout на котором располагаются кнопки
     */
    private void createButton(final ScreenFinishInfoItem.Buttons button,
                              final String needPositiveComment,
                              final String needNegativeComment,
                              final LinearLayout actions) {
        AButton action = new AButton(activity);
        action.setText(button.getLabel());
        action.setBackground((button.getColor().equals(ActivityConst.POSITIVE) ? AButton.GREEN : AButton.RED));
        action.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (button.getSignal().equals("got_agree")) {
                    if (needPositiveComment.equals("true")) {
                        if (!TextUtils.isEmpty(commentText.getText())) {
                            finish(button.getSignal());
                        } else {
                            AppMsg.makeText(activity, getString(R.string.enter_comment), AppMsg.STYLE_ALERT).show();
                        }
                    } else {
                        finish(button.getSignal());
                    }
                } else if (button.getSignal().equals("got_refuse")) {
                    if (needNegativeComment.equals("true")) {
                        if (!TextUtils.isEmpty(commentText.getText())) {
                            finish(button.getSignal());
                        } else {
                            AppMsg.makeText(activity, getString(R.string.enter_comment), AppMsg.STYLE_ALERT).show();
                        }
                    } else {
                        finish(button.getSignal());
                    }
                }
            }
        });
        actions.addView(action);
    }

    /**
     * Метод загружает информацию о документе для получения подписываемых данных
     */
    public void getDocument() {
        new SendGetRequest("rest/api/docflow/doc/document_info?documentID=" +
                documentID + "&locale=" + MyApplication.getLang(), person) {
            @Override
            protected void onPreExecute() {
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(String result) {
                progressBar.setVisibility(View.GONE);
                if (result == null) {
                    AppMsg.makeText(activity, getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                    return;
                }
                try {
                    DocumentItem document = RestClient.getGson().fromJson(result, DocumentItem.class);
                    rawData = document.getRawdata();
                    initSignDocumentComponents();
                } catch (Exception exc) {
                    AppMsg.makeText(activity, getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                    return;
                }
                super.onPostExecute(result);
            }
        }.execute();
    }

    /**
     * Метод отправляет запрос на завершение работы процессом
     *
     * @param signal signal
     */
    private void finish(String signal) {
        String[] signData = new String[2];
        // используется ли ЭЦП
        if (pathToCert != null && password != null) {
            SignManager signManager = new SignManager();
            signManager.setFilePath(pathToCert);
            signManager.setPassword(password);
            signManager.setRawData(rawData);
            signData = signManager.signRawData();
        }
        FinishProcess finish = new FinishProcess();
        finish.setActivity(activity);
        finish.setPerson(person);
        finish.setProcInstID(procInstID);
        finish.setComment(commentText.getText().toString());
        finish.setRawData(rawData);
        finish.setSignal(signal);
        finish.setAddSignature(addSignature.getValue());
        if (signData != null && signData[0] != null && signData[1] != null && certID != null) {
            finish.setCertificate(signData[0]);
            finish.setSignData(signData[1]);
            finish.setCertID(certID);
        }
        finish.setProgressBar(progressBar);
        finish.setActionID(workID);
        finish.setName(name);
        finish.execute();
    }

    /**
     * Подпись документа
     */
    private void signDocument() {
        String[] signData = new String[2];
        // используется ли ЭЦП
        if (pathToCert != null && password != null) {
            SignManager signManager = new SignManager();
            signManager.setFilePath(pathToCert);
            signManager.setPassword(password);
            signManager.setRawData(rawData);
            signData = signManager.signRawData();
        }
        FinishProcess finish = new FinishProcess();
        finish.setActivity(activity);
        finish.setDocumentID(documentID);
        finish.setPerson(person);
        finish.setRawData(rawData);
        finish.setAddSignature(addEDS.getValue());
        if (signData != null && signData[0] != null && signData[1] != null && certID != null) {
            finish.setCertificate(signData[0]);
            finish.setSignData(signData[1]);
            finish.setCertID(certID);
        }
        finish.setProgressBar(progressBar);
        finish.execute();
    }

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

    /**
     * Класс получает с сервера информацию о текущем экране завершения работы
     */
    class BuildActivity extends AsyncTask<Void, Void, String> {

        /**
         * Проверять ли доступность ЭЦП
         */
        boolean checkEDS;

        public BuildActivity(boolean checkEDS) {
            this.checkEDS = checkEDS;
        }

        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(String result) {
            progressBar.setVisibility(View.GONE);
            LinearLayout actions = (LinearLayout) findViewById(R.id.process_finish_info_buttons);
            actions.removeAllViews();
            LinearLayout generalComponentsLayout = (LinearLayout) findViewById(R.id.finish_process_general_components);
            if (result != null) {
                try {
                    ScreenFinishInfoItem params = RestClient.getGson().fromJson(result, ScreenFinishInfoItem.class);
                    rawData = params.getRaw_data();
                    // если необходим ввод комментария
                    if (params.getNeed_comment_input().equals("true")) {
                        commentText.setVisibility(View.VISIBLE);
                    }
                    // включена ли подпись для текущего процесса по умолчанию
                    if (checkEDS) {
                        if (params.getDemandSign().equals("true")) {
                            addSignature.setValue(true);
                            addSignature.setEnabled(false);
                            // требовать ли сертификат при подписи
                            if (person.getSettings().isNeedCert() && person.getSettings().isEnableEDS()) {
                                addEDS.setValue(true);
                                addEDS.setEnabled(false);
                            }
                        }
                    }
                    if (!addEDS.getValue()) {
                        for (int i = 0; i < params.getButtons().length; i++) {
                            createButton(params.getButtons()[i], params.getNeed_enter_positive_comment(),
                                    params.getNeed_enter_negative_comment(), actions);
                        }
                    } else if (password == null || password.isEmpty()) {
                        // кнопка отображающая диалог выбора файла эцп
                        AButton action = new AButton(activity);
                        action.setText(R.string.subscribe);
                        action.setBackground(AButton.GREEN);
                        action.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                signButtonTap();
                            }
                        });
                        actions.addView(action);
                    } else {
                        informationButton.setVisibility(View.VISIBLE);
                        for (int i = 0; i < params.getButtons().length; i++) {
                            createButton(params.getButtons()[i], params.getNeed_enter_positive_comment(),
                                    params.getNeed_enter_negative_comment(), actions);
                        }
                        // кнопка изменяющая файл эцп
                        AButton action = new AButton(activity);
                        action.setText(R.string.change_eds);
                        action.setBackground(AButton.GRAY);
                        action.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                changeSignButtonTap();
                            }
                        });
                        actions.addView(action);
                    }
                    generalComponentsLayout.setVisibility(View.VISIBLE);
                    actions.setVisibility(View.VISIBLE);
                } catch (Exception exc) {
                    AppMsg.makeText(activity, getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                }
            } else if (Utils.checkSyncEnables(settings)) {
                try {
                    ScreenFinishInfoItem item = new FinishProcessTable(activity).get(workID);
                    if (item.getNeed_comment_input().equals("true")) {
                        commentText.setVisibility(View.VISIBLE);
                    }
                    ScreenFinishInfoItem.Buttons[] buttons = RestClient.getGson().
                            fromJson(item.getButtonsString(), ScreenFinishInfoItem.Buttons[].class);
                    if (buttons != null && buttons.length != 0) {
                        item.setButtons(buttons);
                    }
                    for (int i = 0; i < item.getButtons().length; i++) {
                        createButton(item.getButtons()[i], item.getNeed_enter_positive_comment(),
                                item.getNeed_enter_negative_comment(), actions);
                    }
                    generalComponentsLayout.setVisibility(View.VISIBLE);
                    actions.setVisibility(View.VISIBLE);
                } catch (Exception exc) {
                    AppMsg.makeText(activity, getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
                }
            } else {
                AppMsg.makeText(activity, getString(R.string.error_request), AppMsg.STYLE_ALERT).show();
            }
            super.onPostExecute(result);
        }

        @Override
        protected String doInBackground(Void... voids) {
            return new SendGetRequest(person).requestGET(person.getHost() +
                    "rest/api/workflow/process_info?workID=" + workID + "&locale=" + MyApplication.getLang());
        }
    }
}
