/*
 * MoasdaWiki App
 * Copyright (C) 2008 - 2022 Herbert Reiter (herbert@moasdawiki.net)
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3 as published
 * by the Free Software Foundation (GPL-3.0-only).
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
 */

package net.moasdawiki.app;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;

import net.moasdawiki.base.Settings;
import net.moasdawiki.service.repository.RepositoryService;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {

    private static final String TAG = "SettingsFragment";
    private SynchronizeWikiClient synchronizeWikiClient;
    private RepositoryService repositoryService;
    private Settings settings;
    private ExecutorService synchronizationExecutorService;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WikiEngineApplication app = (WikiEngineApplication) getContext().getApplicationContext();
        synchronizeWikiClient = app.getSynchronizeWikiClient();
        repositoryService = app.getRepositoryService();
        settings = app.getSettings();
        synchronizationExecutorService = Executors.newSingleThreadExecutor();
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, @Nullable String rootKey) {
        setPreferencesFromResource(R.xml.settings_fragment, rootKey);

        EditTextPreference preference = findPreference("sync_server_port");
        if (preference != null) {
            preference.setOnBindEditTextListener(editText -> {
                editText.setInputType(InputType.TYPE_CLASS_NUMBER);
                editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(5)});
            });
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
        updateSettingsSummaries();
        updateStatusText();
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        updateSettingsSummaries();

        if ("sync_server_host".equals(key) || "sync_server_port".equals(key)) {
            checkServerConnection();
        }
    }

    private void showToast(String message) {
        Toast toast = Toast.makeText(getContext(), message, Toast.LENGTH_SHORT);
        toast.show();
    }

    private void updateSettingsSummaries() {
        // Host name
        SharedPreferences preferences = getPreferenceManager().getSharedPreferences();
        String serverHost = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST, null);
        EditTextPreference syncServerHost = findPreference("sync_server_host");
        if (syncServerHost != null) {
            if (serverHost != null && !serverHost.isEmpty()) {
                syncServerHost.setSummary(serverHost);
            } else {
                syncServerHost.setSummary(R.string.settings_host_summary_empty);
            }
        }

        // Port
        String serverPort = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_PORT, null);
        EditTextPreference syncServerPort = findPreference("sync_server_port");
        if (syncServerPort != null) {
            if (serverPort != null && !serverPort.isEmpty()) {
                syncServerPort.setSummary(serverPort);
            } else {
                String summary = getString(R.string.settings_port_summary_empty, settings.getServerPort());
                syncServerPort.setSummary(summary);
            }
        }
    }

    private void updateStatusText() {
        SharedPreferences preferences = getPreferenceManager().getSharedPreferences();
        String serverSessionId = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_SESSION_ID, null);
        boolean serverSessionAuthorized = preferences.getBoolean(Constants.PREFERENCES_SYNC_SERVER_SESSION_AUTHORIZED, false);
        String serverHost = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST, null);
        String serverHostDisplayName = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST_DISPLAYNAME, "");

        // Connection status
        String connectionStatus;
        if (serverSessionId == null) {
            connectionStatus = getString(R.string.settings_status_server_not_connected);
        } else if (!serverSessionAuthorized) {
            connectionStatus = getString(R.string.settings_status_server_authorization_mission);
        } else {
            connectionStatus = getString(R.string.settings_status_server_connected);
        }

        // Server Host
        String serverHostCombined = serverHostDisplayName;
        if (!serverHostCombined.isEmpty() && serverHost != null) {
            serverHostCombined += " (" + serverHost + ")";
        }

        // Last synchronization timestamp
        long lastSyncTimeMs = preferences.getLong(Constants.PREFERENCES_SYNC_SERVER_TIME, 0);
        String lastSyncStr = "";
        if (lastSyncTimeMs > 0) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
            lastSyncStr = df.format(new Date(lastSyncTimeMs));
        }

        // Number of files in repository
        int filesCount = repositoryService.getFiles().size();
        String filesCountStr = Integer.toString(filesCount);

        String htmlText = getString(R.string.settings_status_details, connectionStatus, serverHostCombined, lastSyncStr, filesCountStr);
        Preference synchronizationStatus = findPreference("synchronization_status");
        if (synchronizationStatus != null) {
            synchronizationStatus.setSummary(htmlText);
        }
    }

    /**
     * Called if the user changes the connection settings to give fast feedback.
     */
    private void checkServerConnection() {
        synchronizationExecutorService.submit(this::runCheckServerConnection);
    }

    /**
     * Run server connection check.
     * This method is run in an asynchronous background thread.
     */
    private void runCheckServerConnection() {
        SharedPreferences preferences = getPreferenceManager().getSharedPreferences();
        String host = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST, null);
        if (host == null) {
            Log.d(TAG, "Cancel ConnectServerTask because server host is not configured");
            return;
        }

        boolean success = synchronizeWikiClient.createAndCheckSession();
        updateStatusText();

        if (!success) {
            showToast(getString(R.string.settings_search_failed));
        }
    }
}
