package com.angryburg.uapp.activities;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;

import com.angryburg.uapp.R;
import com.angryburg.uapp.fragments.AwooEndpointFragment;
import com.angryburg.uapp.fragments.ColorListFragment;
import com.angryburg.uapp.fragments.ColorPickerFragment;
import com.angryburg.uapp.fragments.DebugSettingsListFragment;
import com.angryburg.uapp.fragments.HiddenThreadListFragment;
import com.angryburg.uapp.fragments.NewPropertyFragment;
import com.angryburg.uapp.fragments.NotificationSettingsFragment;
import com.angryburg.uapp.fragments.PropertiesListFragment;
import com.angryburg.uapp.fragments.PropertyEditorFragment;
import com.angryburg.uapp.fragments.SettingsListFragment;
import com.angryburg.uapp.fragments.HiddenSettingsFragment;
import com.angryburg.uapp.fragments.JanitorLoginFragment;
import com.angryburg.uapp.fragments.ThreadWatcherFragment;
import com.angryburg.uapp.utils.P;
import com.angryburg.uapp.utils.WindowUtils;

import java.util.Stack;

/**
 * An activity that can display multiple fragments.
 * It expects a "fragment" to be passed in through the intent, and it will put that fragment
 * in its frame. That fragment can call swapScreen on this activity to switch to a different fragment
 * When the user presses the back button, it will swapScreen back to the fragment from the intent if
 * it wasn't already there, or finish() if it was.
 */

public class HiddenSettingsActivity extends Activity {
    @SuppressWarnings("unused")
    private static final String TAG = HiddenSettingsActivity.class.getSimpleName();
    private Stack<FragmentType> windowStack;
    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (P.getBool("dark_mode")) setTheme(R.style.AppTheme_Dark);
        setContentView(R.layout.userscript_activity);
        invalidateToolbarColor();
        FragmentType type = FragmentType.DEBUG_SETTINGS_LIST;
        windowStack = new Stack<>();
        if (savedInstanceState != null && savedInstanceState.containsKey("stack")) {
            //noinspection unchecked
            String[] arr = savedInstanceState.getStringArray("stack");
            if (arr != null) {
                windowStack = new Stack<>();
                for (String val : arr) {
                    windowStack.push(FragmentType.valueOf(val));
                }
                type = windowStack.peek();
            }
        } else if (getIntent().hasExtra("fragment") && savedInstanceState == null){
            type = FragmentType.valueOf(getIntent().getStringExtra("fragment"));
            windowStack.push(type);
        } else {
            windowStack.push(type);
        }
        swapScreens(type);
    }
    @Override public void onBackPressed() {
        if (windowStack.isEmpty() || windowStack.size() == 1) {
            finish();
            return;
        }
        pop();
    }

    /**
     * Replaces the top of the fragment stack with the given fragment type
     * @param type The fragment to replace
     * @param args The arguments to pass to that fragment
     */
    public void replace(FragmentType type, Bundle args) {
        windowStack.pop();
        windowStack.push(type);
        swapScreens(type, args);
    }

    /**
     * Pushes another fragment onto the fragment stack
     * @param type the type of fragment to put on the stack
     * @param args optional arguments to pass to the fragment
     */
    public void push(FragmentType type, Bundle args) {
        windowStack.push(type);
        swapScreens(type, args);
    }

    /**
     * Pushes another fragment onto the fragment stack
     * @param type the type of fragment to put on the stack
     */
    public void push(FragmentType type) {
        push(type, null);
    }

    /**
     * Pops the top fragment off the stack.
     */
    public void pop() {
        windowStack.pop();
        if (windowStack.isEmpty()) {
            finish();
            return;
        }
        swapScreens(windowStack.peek());
    }
    private void swapScreens(FragmentType type) {
        swapScreens(type, null);
    }
    /**
     * Switches to the passed fragment
     * If the currently shown fragment has the same type as the argument, does nothing. Otherwise,
     * removes the current fragment and makes a new fragment of the passed in type and shows it
     * @param type the fragment to switch to
     * @param arguments arguments to give to the fragment
     */
    private void swapScreens(FragmentType type, @Nullable Bundle arguments) {
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        // if we already have a fragment and that fragment is not the fragment we want to show, remove it
        // otherwise, it is the fragment we want to show, so we're done, just return and abort the transaction
        if (manager.findFragmentByTag("fragment") != null) {
            if (((HiddenSettingsFragment) manager.findFragmentByTag("fragment")).getType() != type) {
                transaction.remove(manager.findFragmentByTag("fragment"));
            } else {
                return;
            }
        }
        // Make a new fragment
        Fragment newFragment = null;
        switch (type) {
            case SETTINGS_LIST:
                newFragment = new SettingsListFragment();
                break;
            case JANITOR_LOGIN:
                newFragment = new JanitorLoginFragment();
                break;
            case THREAD_WATCHER:
                newFragment = new ThreadWatcherFragment();
                break;
            case AWOO_ENDPOINT:
                newFragment = new AwooEndpointFragment();
                break;
            case DEBUG_SETTINGS_LIST:
                newFragment = new DebugSettingsListFragment();
                break;
            case COLOR_LIST:
                newFragment = new ColorListFragment();
                break;
            case PROPERTY_EDITOR:
                newFragment = new PropertyEditorFragment();
                break;
            case PROPERTY_EDITOR_NEW:
                newFragment = new NewPropertyFragment();
                break;
            case PROPERTIES_LIST:
                newFragment = new PropertiesListFragment();
                break;
            case HIDDEN_LIST:
                newFragment = new HiddenThreadListFragment();
                break;
            case NOTIFICATION_SETTINGS:
                newFragment = new NotificationSettingsFragment();
                break;
            case COLOR_PICKER:
                newFragment = new ColorPickerFragment();
                break;
        }
        newFragment.setArguments(arguments);
        // Put the fragment in our layout
        //transaction.add(newFragment, "fragment");
        transaction.replace(R.id.userscript_activity_main_fragment, newFragment, "fragment");
        transaction.addToBackStack("fragment"); // TODO is this needed?
        transaction.commit();
    }

    /**
     * Save the currently shown fragment type to the saved instance state so it can be restored
     * @param outState state to be saved
     */
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String[] arr = new String[windowStack.size()];
        int i = 0;
        for (FragmentType t : windowStack.toArray(new FragmentType[windowStack.size()]))
            //noinspection ValueOfIncrementOrDecrementUsed
            arr[i++] = t.toString();
        outState.putStringArray("stack", arr);
    }

    /**
     * Refreshes the toolbar color from the properties.
     */
    public void invalidateToolbarColor() {
        try {
            Toolbar toolbar = findViewById(R.id.toolbar);
            toolbar.setBackgroundColor(P.getColor("toolbar_color"));
            WindowUtils.updateWindowBarColor(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Types of fragments that can be embedded in this activity
     */
    @SuppressWarnings("JavaDoc")
    public enum FragmentType {
        SETTINGS_LIST,
        DEBUG_SETTINGS_LIST,
        JANITOR_LOGIN,
        THREAD_WATCHER,
        COLOR_LIST,
        AWOO_ENDPOINT,
        PROPERTY_EDITOR,
        PROPERTY_EDITOR_NEW,
        PROPERTIES_LIST,
        COLOR_PICKER,
        HIDDEN_LIST,
        NOTIFICATION_SETTINGS
    }
}