public class PresetStoreInstalledFragment extends Fragment implements Refreshable {

    private WindowHelper window = new WindowHelper();
    private AnimateHelper anim = new AnimateHelper();
    private FileHelper fileHelper = new FileHelper();

    private String TAG = "PSInstalled";

    AppCompatActivity a;
    View v;
    Gson gson;

    public PresetStoreAdapter installedAdapter = null;

    private File[] presets;

    public PresetStoreInstalledFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_preset_store_installed, container, false);
    }
    
    @Override
    public void onStart() {
        super.onStart();

        v = getView();
        setUi();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        a = (AppCompatActivity) getActivity();
        gson = new GsonBuilder().setPrettyPrinting().create();
    }

    void setUi() {
        // adapter
        LinearLayoutManager layoutManager = new LinearLayoutManager(a);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        ((RecyclerView) v.findViewById(R.id.layout_installed_preset_store_recycler_view)).setLayoutManager(layoutManager);
        ((RecyclerView) v.findViewById(R.id.layout_installed_preset_store_recycler_view)).setNestedScrollingEnabled(false);

        setAdapter();
    }

    String tapadFolderPath = Environment.getExternalStorageDirectory().getPath() + "/Tapad";

    class ScanLocal extends AsyncTask<Void, Void, Void> {

        ArrayList<PresetSchema> presetArrayList;

        @Override
        protected void onPreExecute() {
            presets = getPresetFolderList();
            presetArrayList = new ArrayList<>();

            if (presets == null || presets.length <= 0) {
                cancel(true);
            }
        }

        @Override
        protected Void doInBackground(Void... voids) {
            for (File presetFolder : presets) {
                if (fileHelper.isPresetMetadataAvailable(presetFolder.getName())) {
                    // check folder's presets
                    if (validateMetadata(presetFolder.getName())) {
                        // pass only JSON v2
                        presetArrayList.add(fileHelper.getPresetSchemaFromMetadata(presetFolder.getName(), gson));
                        Log.i(TAG, presetFolder.getName() + " exists");
                    } else {
                        Log.e(TAG, presetFolder.getName() + " Json is outdated or corrupted");
                    }
                }
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            // create metadata
            if (presetArrayList.size() > 0) {
                installed = new PresetStore(
                        presetArrayList.toArray(new PresetSchema[presetArrayList.size()]),
                        new Preferences(a)
                );
                setAdapter();
            } else {
                onCancelled();
            }
        }

        @Override
        protected void onCancelled() {
            // need to show no presets installed
            // TODO need to add additional dialog supports
            Log.e(TAG, "Cannot find installed presets");
            installed = new PresetStore();
            setAdapter();
        }
    }

    private void searchMetadata() {
        new ScanLocal().execute();
    }

    private boolean validateMetadata(String presetName) {
        String metadata = fileHelper.getStringFromFile(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/json");
        if (metadata.contains("firebase_location")) {
            // JSON v1, need to be updated
            return false;
        } else if (metadata.contains("tag")) {
            // JSON v2
            return true;
        } else {
            // corrupted JSON
            return false;
        }
    }

    private File[] getPresetFolderList() {
        return new File(tapadFolderPath + "/presets").listFiles();
    }

    private void setAdapter() {
        Log.d(TAG, "setAdapter");
        // attach the adapter to the layout
        if (installed == null) {
            // not initialized
            searchMetadata();
        } else if (installed.getLength() <= 0) {
            // clear the recycler view
            attachAdapter();
            window.setGone(R.id.layout_installed_preset_store_recycler_view, 0, a);
            anim.fadeIn(R.id.layout_installed_preset_store_recycler_view_no_preset, 0, 200, "rvNoPresetIn", v, a);
        } else {
            if ((v.findViewById(R.id.layout_installed_preset_store_recycler_view_no_preset)).getVisibility()
                    == View.VISIBLE) {
                // no preset visible
                window.setGone(R.id.layout_installed_preset_store_recycler_view_no_preset, 0, a);
                anim.fadeIn(R.id.layout_installed_preset_store_recycler_view, 0, 200, "rvNoPresetIn", v, a);
            }
            attachAdapter();
        }
    }

    private void attachAdapter() {
        // attach adapter while its not null
        if (installed != null && installed.getLength() > 0) {
            Log.d(TAG, "Attached adapter");
            installedAdapter = new PresetStoreAdapter(
                    installed,
                    R.layout.adapter_preset_store, a
            );
            installedAdapter.setCallingFragment("installed");
            ((RecyclerView) v.findViewById(R.id.layout_installed_preset_store_recycler_view)).setAdapter(installedAdapter);
        } else {
            Log.d(TAG, "Metadata is null");
        }
    }

    @Override
    public void refresh() {
        searchMetadata();
    }

    @Override
    public void clear() {
        window.setGone(R.id.layout_installed_preset_store_recycler_view, 0, a);
        refresh();
    }
} public class PresetStoreOnlineFragment extends Fragment implements Refreshable {

    private WindowHelper window = new WindowHelper();
    private AnimateHelper anim = new AnimateHelper();
    private ApiHelper api = new ApiHelper();

    private boolean isUpdateDialogShown = false;

    private String TAG = "PSOnline";

    AppCompatActivity a;
    View v;

    public PresetStoreAdapter presetStoreAdapter = null;

    public PresetStoreOnlineFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_preset_store_online, container, false);
    }

    @Override
    public void onStart() {
        super.onStart();

        v = getView();
        setUi();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        a = (AppCompatActivity) getActivity();
    }

    RecyclerView recyclerView = null;
    View recyclerViewLoading = null;
    View recyclerViewFailed = null;
    View recyclerViewFailedRetry = null;

    void setUi() {
        recyclerView = ((RecyclerView) v.findViewById(R.id.layout_online_preset_store_recycler_view));
        recyclerViewLoading = (v.findViewById(R.id.layout_online_preset_store_recycler_view_loading));
        recyclerViewFailed = (v.findViewById(R.id.layout_online_preset_store_recycler_view_failed));
        recyclerViewFailedRetry = (v.findViewById(R.id.layout_online_preset_store_recycler_view_failed_retry));

        // adapter
        LinearLayoutManager layoutManager = new LinearLayoutManager(a);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setNestedScrollingEnabled(false);
    }

    public void setLoadingFinished(boolean isFinished) {
        if (isFinished) {
            // finished, hide loading and show recyclerView
            Log.d(TAG, "setLF(true)");
            anim.fadeOut(recyclerViewLoading, 0, 200, a);
            anim.fadeOut(recyclerViewFailed, 0, 200, a);
            anim.fadeOut(recyclerViewFailedRetry, 0, 200, a);
            if (recyclerView.getVisibility() != View.VISIBLE) {
                anim.fadeIn(recyclerView, 200, 200, "rvIn", a);
            }
        } else {
            // started, show loading
            Log.d(TAG, "setLF(false)");
            anim.fadeOut(recyclerView, 0, 200, a);
            anim.fadeOut(recyclerViewFailed, 0, 200, a);
            anim.fadeOut(recyclerViewFailedRetry, 0, 200, a);
            anim.fadeOut(recyclerViewLoading, 0, 200, a);
            if (recyclerViewLoading.getVisibility() != View.VISIBLE) {
                anim.fadeIn(recyclerViewLoading, 200, 200, "rvLoadingIn", a);
            }
            // cancel the timeout check
            connectionTimeout.removeCallbacksAndMessages(null);
        }
    }

    private void setLoadingFailed(boolean isFailed) {
        if (isFailed) {
            Log.e(TAG, "Loading failed");
            anim.fadeOut(recyclerView, 0, 200, a);
            anim.fadeOut(recyclerViewLoading, 0, 200, a);
            anim.fadeIn(recyclerViewFailed, 200, 200, "rvIn", a);
            recyclerViewFailedRetry.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // retry button
                    setAdapter();
                }
            });
            Handler handler = new Handler();
            if (((TabLayout) (a.findViewById(R.id.layout_tab_layout))).getSelectedTabPosition() == 1) {
                // only when the online tab is selected
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        new MaterialDialog.Builder(a)
                                .title(R.string.preset_store_download_no_connection_dialog_title)
                                .content(R.string.preset_store_download_no_connection_dialog_text)
                                .contentColorRes(R.color.dark_primary)
                                .neutralText(R.string.dialog_close)
                                .show();
                    }
                }, 200);
            }
        } else {
            Log.d(TAG, "Reset failed error");
            anim.fadeIn(recyclerView, 0, 200, "rvIn", a);
            anim.fadeIn(recyclerViewLoading, 0, 200, "rvLIn", a);
            anim.fadeOut(recyclerViewFailed, 200, 200, a);
        }
    }

    private Handler connectionTimeout = new Handler();

    private void setAdapter() {
        if (isPresetDownloading) {
            // attach adapter while its not null
            presetStoreAdapter = new PresetStoreAdapter(
                    online,
                    R.layout.adapter_preset_store, a
            );
            Log.i(TAG, "Currently downloading, show progress");
            presetStoreAdapter.setCallingFragment("online");
            ((RecyclerView) v.findViewById(R.id.layout_online_preset_store_recycler_view)).setAdapter(presetStoreAdapter);
            setLoadingFinished(true);
        } else {
            connectionTimeout.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if ((v.findViewById(R.id.layout_online_preset_store_recycler_view_loading)).getVisibility() == View.VISIBLE) {
                        // loading for 10 seconds, prompt user to retry or not
                        if (((TabLayout) (a.findViewById(R.id.layout_tab_layout))).getSelectedTabPosition() == 1) {
                            // only when the online page is visible
                            setLoadingFailed(true);
                            if (a != null) {
                                new MaterialDialog.Builder(a)
                                        .title(R.string.preset_store_connection_timeout_dialog_title)
                                        .content(R.string.preset_store_connection_timeout_dialog_text)
                                        .contentColorRes(R.color.dark_primary)
                                        .positiveText(R.string.preset_store_connection_timeout_dialog_positive)
                                        .negativeText(R.string.preset_store_connection_timeout_dialog_negative)
                                        .onPositive(new MaterialDialog.SingleButtonCallback() {
                                            @Override
                                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                                setAdapter();
                                            }
                                        })
                                        .onNegative(new MaterialDialog.SingleButtonCallback() {
                                            @Override
                                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                                dialog.dismiss();
                                            }
                                        })
                                        .show();
                            }
                        }
                    }
                }
            }, 10000);

            if (isConnected(a)) {
                Log.d(TAG, "setAdapter");
                // attach the adapter to the layout
                api.getObservableSchema().subscribe(new Subscriber<Schema>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, "Error parsing schema, " + e.getMessage());
                    }

                    @Override
                    public void onNext(Schema schema) {
                        if (schema == null ||
                                schema.getPresets() == null ||
                                schema.getVersion() == null) {
                            // corrupted schema
                            Log.e(TAG, "Schema is null");
                            setLoadingFailed(true);
                        } else {
                            // version check
                            int version = -1;

                            try {
                                PackageInfo pInfo = a.getPackageManager().getPackageInfo(a.getPackageName(), 0);
                                version = pInfo.versionCode;
                            } catch (PackageManager.NameNotFoundException e) {
                                e.printStackTrace();
                            }

                            if (((TabLayout) (a.findViewById(R.id.layout_tab_layout))).getSelectedTabPosition() == 1) {
                                // only when the online page is visible
                                if (isUpdateDialogShown == false
                                        && version > 0
                                        && schema.getVersion() > version) {
                                    // currently using outdated version, show dialog
                                    new MaterialDialog.Builder(a)
                                            .title(R.string.preset_store_outdated_version_dialog_title)
                                            .content(R.string.preset_store_outdated_version_dialog_text)
                                            .contentColorRes(R.color.dark_primary)
                                            .positiveText(R.string.preset_store_outdated_version_dialog_positive)
                                            .negativeText(R.string.preset_store_outdated_version_dialog_negative)
                                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                                @Override
                                                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                                    new IntentHelper().intentMarket(a, APPLICATION_ID, 0);
                                                }
                                            })
                                            .onNegative(new MaterialDialog.SingleButtonCallback() {
                                                @Override
                                                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                                    dialog.dismiss();
                                                }
                                            })
                                            .dismissListener(new DialogInterface.OnDismissListener() {
                                                @Override
                                                public void onDismiss(DialogInterface dialogInterface) {
                                                    // show dialog only once
                                                    isUpdateDialogShown = true;
                                                }
                                            })
                                            .show();
                                }
                            }

                            if (online == null) {
                                online = new PresetStore(schema.getPresets(), new Preferences(a));
                            } else {
                                // savedState
                                if (!isPresetDownloading) {
                                    PresetStore updated = new PresetStore(schema.getPresets(), new Preferences(a));
                                    if (online.getLength() < updated.getLength()) {
                                        // updated
                                        online = updated;
                                    }
                                }
                            }

                            // attach adapter while its not null
                            presetStoreAdapter = new PresetStoreAdapter(
                                    online,
                                    R.layout.adapter_preset_store, a
                            );
                            presetStoreAdapter.setCallingFragment("online");
                            ((RecyclerView) v.findViewById(R.id.layout_online_preset_store_recycler_view)).setAdapter(presetStoreAdapter);
                            setLoadingFinished(true);
                        }
                    }
                });
            } else {
                setLoadingFailed(true);
            }
        }
    }

    private boolean isConnected(Context context) {
        // returns whether the device is connected to the internet
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    @Override
    public void refresh() {
        Log.d(TAG, "refresh");
        setAdapter();
    }

    @Override
    public void clear() {
        Log.i(TAG, "clear()");
        if (recyclerView != null && recyclerView.getVisibility() != View.GONE) {
            recyclerView.setVisibility(View.GONE);
        }

        if (recyclerViewLoading != null && recyclerViewLoading.getVisibility() != View.VISIBLE) {
            recyclerViewLoading.setVisibility(View.VISIBLE);
        }
        refresh();
    }
} public interface Refreshable {

    void refresh();

    void clear();
} @TargetApi(14)
public class AnimateHelper {
    private WindowHelper window = new WindowHelper();

    static String TAG = "AnimateHelper";

    // Fade animations

    public static String getViewId(View view) {
        String name = view.toString();
        return name.substring(name.lastIndexOf("/") + 1, name.lastIndexOf("}"));
    }

    public void fade(final int id, final float startAlpha, final float endAlpha, final int delay, final long duration, String handlerName, Activity activity) {
        final AlphaAnimation fade = new AlphaAnimation(startAlpha, endAlpha);
        final View view = activity.findViewById(id);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setAlpha(endAlpha);

                        Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for 0ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setAlpha(endAlpha);
                Log.i(TAG,
                        getViewId(view) + " fade effect to " +
                                String.valueOf(endAlpha) + "f for 0ms with no delay");
            }
        } else {
            // normal fade out
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fade.setDuration(duration);
                        fade.setAnimationListener(new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animation animation) {

                            }

                            @Override
                            public void onAnimationRepeat(Animation animation) {

                            }
                        });
                        view.startAnimation(fade);
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG,
                                getViewId(view) + " fade effect from " +
                                        String.valueOf(startAlpha) + "f to " +
                                        String.valueOf(endAlpha) + "f for " +
                                        String.valueOf(duration) + "ms with " +
                                        String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fade.setDuration(duration);
                view.startAnimation(fade);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG,
                        getViewId(view) + " fade effect from " +
                                String.valueOf(startAlpha) + "f to " +
                                String.valueOf(endAlpha) + "f for " +
                                String.valueOf(duration) + "ms with no delay");
            }

            fade.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    view.setAlpha(startAlpha);
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    view.setAlpha(endAlpha);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        }
    }

    public void fadeIn(final int id, final int delay, final long duration, String handlerName, Activity activity) {
        final AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
        final View view = activity.findViewById(id);
        view.setVisibility(View.INVISIBLE);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG, getViewId(view) + " fade IN [VISIBLE] effect for 0ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setVisibility(View.VISIBLE);
                Log.i(TAG,
                        getViewId(view) + " fade IN effect to 1.0f for 0ms with no delay");
            }
        } else {
            // normal fadeIn IN
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeIn.setDuration(duration);
                        view.startAnimation(fadeIn);
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG,
                                getViewId(view) + " fade IN effect for " +
                                        String.valueOf(duration) + "ms with " +
                                        String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fadeIn.setDuration(duration);
                view.startAnimation(fadeIn);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG,
                        getViewId(view) + " fade IN effect for " +
                                String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    public void fadeIn(final View view, final int delay, final long duration, String handlerName, Activity activity) {
        final AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
        view.setVisibility(View.INVISIBLE);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG, getViewId(view) + " fade IN [VISIBLE] effect for 0ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setVisibility(View.VISIBLE);
                Log.i(TAG,
                        view.getId() + " fade IN effect to 1.0f for 0ms with no delay");
            }
        } else {
            // normal fadeIn IN
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeIn.setDuration(duration);
                        view.startAnimation(fadeIn);
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG,
                                getViewId(view) + " fade IN effect for " +
                                        String.valueOf(duration) + "ms with " +
                                        String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fadeIn.setDuration(duration);
                view.startAnimation(fadeIn);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG,
                        getViewId(view) + " fade IN effect for " +
                                String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    public void fadeIn(final int id, final int delay, final long duration, String handlerName, View parentView, Activity activity) {
        final AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
        final View view = parentView.findViewById(id);
        view.setVisibility(View.INVISIBLE);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG, getViewId(view) + " fade IN [VISIBLE] effect for 0ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setVisibility(View.VISIBLE);
                Log.i(TAG,
                        getViewId(view) + " fade IN effect to 1.0f for 0ms with no delay");
            }
        } else {
            // normal fadeIn IN
            if (duration > 0) {
                // delay, needs an handler
                Map<String, Handler> handlerCreator = new HashMap<>();
                handlerCreator.put(handlerName, new Handler());

                handlerCreator.get(handlerName).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeIn.setDuration(duration);
                        view.startAnimation(fadeIn);
                        view.setVisibility(View.VISIBLE);

                        Log.i(TAG,
                                getViewId(view) + " fade IN effect for " +
                                        String.valueOf(duration) + "ms with " +
                                        String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fadeIn.setDuration(duration);
                view.startAnimation(fadeIn);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG,
                        getViewId(view) + " fade IN effect for " +
                                String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    public void fadeOut(final int id, final int delay, final long duration, Activity activity) {
        final AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
        final View view = activity.findViewById(id);

        if (view.getVisibility() == View.VISIBLE) {
            PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

            if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
                // power save mode on
                if (duration > 0) {
                    // delay, needs an handler
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);

                            Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                        }
                    }, delay);
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);
                        }
                    }, delay + duration + 10);
                } else {
                    view.setVisibility(View.GONE);
                    Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with no delay");
                }
            } else {
                // normal fade out
                if (duration > 0) {
                    // delay, needs an handler
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            fadeOut.setDuration(duration);
                            view.startAnimation(fadeOut);

                            Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                        }
                    }, delay);
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);
                        }
                    }, delay + duration + 10);
                } else {
                    fadeOut.setDuration(duration);
                    view.setVisibility(View.GONE);
                    Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with no delay");
                }
            }
        }
    }

    public void fadeOut(final View view, final int delay, final long duration, Activity activity) {
        final AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);

        if (view.getVisibility() == View.VISIBLE) {
            PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

            if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
                // power save mode on
                if (duration > 0) {
                    // delay, needs an handler
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);

                            Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                        }
                    }, delay);
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);
                        }
                    }, delay + duration + 10);
                } else {
                    view.setVisibility(View.GONE);
                    Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with no delay");
                }
            } else {
                // normal fade out
                if (duration > 0) {
                    // delay, needs an handler
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            fadeOut.setDuration(duration);
                            view.startAnimation(fadeOut);

                            Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                        }
                    }, delay);
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            view.setVisibility(View.GONE);
                        }
                    }, delay + duration + 10);
                } else {
                    fadeOut.setDuration(duration);
                    view.setVisibility(View.GONE);
                    Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with no delay");
                }
            }
        }
    }

    public void fadeOut(final int id, final int delay, final long duration, View parentView, Activity activity) {
        final AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
        final View view = parentView.findViewById(id);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.GONE);

                        Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.GONE);
                    }
                }, delay + duration + 10);
            } else {
                view.setVisibility(View.GONE);
                Log.i(TAG, getViewId(view) + " fade OUT [GONE] effect for " + String.valueOf(duration) + "ms with no delay");
            }
        } else {
            // normal fade out
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeOut.setDuration(duration);
                        view.startAnimation(fadeOut);

                        Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.GONE);
                    }
                }, delay + duration + 10);
            } else {
                fadeOut.setDuration(duration);
                view.setVisibility(View.GONE);
                Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    public void fadeOutInvisible(final int id, final int delay, final long duration, Activity activity) {
        final AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
        final View view = activity.findViewById(id);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.INVISIBLE);

                        Log.i(TAG, getViewId(view) + " fade OUT [INVISIBLE] effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setVisibility(View.INVISIBLE);
                Log.i(TAG, getViewId(view) + " fade OUT [INVISIBLE] effect for " + String.valueOf(duration) + "ms with no delay");
            }
        } else {
            // normal fade out
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeOut.setDuration(duration);
                        view.startAnimation(fadeOut);
                        view.setVisibility(View.INVISIBLE);

                        Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fadeOut.setDuration(duration);
                view.startAnimation(fadeOut);
                view.setVisibility(View.INVISIBLE);
                Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    public void fadeOutInvisible(final int id, final int delay, final long duration, View parentView, Activity activity) {
        final AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
        final View view = parentView.findViewById(id);
        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode()) {
            // power save mode on
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.INVISIBLE);

                        Log.i(TAG, getViewId(view) + " fade OUT [INVISIBLE] effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                view.setVisibility(View.INVISIBLE);
                Log.i(TAG, getViewId(view) + " fade OUT [INVISIBLE] effect for " + String.valueOf(duration) + "ms with no delay");
            }
        } else {
            // normal fade out
            if (duration > 0) {
                // delay, needs an handler
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        fadeOut.setDuration(duration);
                        view.startAnimation(fadeOut);
                        view.setVisibility(View.INVISIBLE);

                        Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                    }
                }, delay);
            } else {
                fadeOut.setDuration(duration);
                view.startAnimation(fadeOut);
                view.setVisibility(View.INVISIBLE);
                Log.i(TAG, getViewId(view) + " fade OUT effect for " + String.valueOf(duration) + "ms with no delay");
            }
        }
    }

    // Slide Animations

    public void slideIn(final View view, final int delay, final long duration, String handlerName) {
        final TranslateAnimation slideIn = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1, Animation.RELATIVE_TO_SELF, 0);
        view.setVisibility(View.INVISIBLE);

        slideIn.setInterpolator(new DecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.VISIBLE);
                slideIn.setDuration(duration);
                view.startAnimation(slideIn);

                Log.i(TAG, "slide IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);
    }

    // Scale Animations

    public void scaleOut(final View view, final int delay, final long duration, String handlerName) {
        final ScaleAnimation scaleOut = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        if (delay > 0) {
            handlerCreator.get(handlerName).postDelayed(new Runnable() {
                @Override
                public void run() {
                    view.setVisibility(View.VISIBLE);
                    scaleOut.setDuration(duration);
                    view.startAnimation(scaleOut);

                    Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                }
            }, delay);
        } else {
            view.setVisibility(View.VISIBLE);
            scaleOut.setDuration(duration);
            view.startAnimation(scaleOut);

            Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
        }

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleOut(final int id, final int delay, final long duration, String handlerName, Activity activity) {
        final View view = activity.findViewById(id);
        final ScaleAnimation scaleOut = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.VISIBLE);
                scaleOut.setDuration(duration);
                view.startAnimation(scaleOut);

                Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleOut(final View view, int touchX, int touchY, final int delay, final long duration, String handlerName, Activity activity) {
        float x = touchX / window.getWindowWidthPx(activity);
        float y = touchY / window.getWindowHeightPx(activity);
        final ScaleAnimation scaleOut = new ScaleAnimation(1, 0, 1, 0, Animation.ABSOLUTE, x, Animation.ABSOLUTE, y);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.VISIBLE);
                scaleOut.setDuration(duration);
                view.startAnimation(scaleOut);

                Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleOut(final int id, int touchX, int touchY, final int delay, final long duration, String handlerName, Activity activity) {
        final View view = activity.findViewById(id);
        float x = touchX / window.getWindowWidthPx(activity);
        float y = touchY / window.getWindowHeightPx(activity);
        final ScaleAnimation scaleOut = new ScaleAnimation(1, 0, 1, 0, Animation.ABSOLUTE, x, Animation.ABSOLUTE, y);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        if (delay > 0) {
            handlerCreator.get(handlerName).postDelayed(new Runnable() {
                @Override
                public void run() {
                    view.setVisibility(View.VISIBLE);
                    scaleOut.setDuration(duration);
                    view.startAnimation(scaleOut);

                    Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                }
            }, delay);
        } else {
            view.setVisibility(View.VISIBLE);
            scaleOut.setDuration(duration);
            view.startAnimation(scaleOut);

            Log.i(TAG, "scale OUT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
        }

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleIn(final View view, final int delay, final long duration, String handlerName) {
        final ScaleAnimation scaleIn = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        view.setVisibility(View.INVISIBLE);

        scaleIn.setInterpolator(new AccelerateDecelerateInterpolator());

        if (delay > 0) {
            Map<String, Handler> handlerCreator = new HashMap<>();
            handlerCreator.put(handlerName, new Handler());

            handlerCreator.get(handlerName).postDelayed(new Runnable() {
                @Override
                public void run() {
                    scaleIn.setDuration(duration);
                    view.startAnimation(scaleIn);
                    view.setVisibility(View.VISIBLE);

                    Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                }
            }, delay);
        } else {
            scaleIn.setDuration(duration);
            view.startAnimation(scaleIn);
            view.setVisibility(View.VISIBLE);

            Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
        }
    }

    public void scaleIn(final int id, final int delay, final long duration, String handlerName, Activity activity) {
        final View view = activity.findViewById(id);
        final ScaleAnimation scaleIn = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        view.setVisibility(View.INVISIBLE);

        scaleIn.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                scaleIn.setDuration(duration);
                view.startAnimation(scaleIn);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);
    }

    public void scaleIn(final View view, int touchX, int touchY, final int delay, final long duration, String handlerName, Activity activity) {
        float x = touchX / window.getWindowWidthPx(activity);
        float y = touchY / window.getWindowHeightPx(activity);
        final ScaleAnimation scaleOut = new ScaleAnimation(0, 1, 0, 1, Animation.ABSOLUTE, x, Animation.ABSOLUTE, y);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.VISIBLE);
                scaleOut.setDuration(duration);
                view.startAnimation(scaleOut);

                Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleIn(final int id, int touchX, int touchY, final int delay, final long duration, String handlerName, Activity activity) {
        final View view = activity.findViewById(id);
        float x = touchX / window.getWindowWidthPx(activity);
        float y = touchY / window.getWindowHeightPx(activity);
        final ScaleAnimation scaleOut = new ScaleAnimation(0, 1, 0, 1, Animation.ABSOLUTE, x, Animation.ABSOLUTE, y);

        scaleOut.setInterpolator(new AccelerateDecelerateInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        if (delay > 0) {
            handlerCreator.get(handlerName).postDelayed(new Runnable() {
                @Override
                public void run() {
                    view.setVisibility(View.VISIBLE);
                    scaleOut.setDuration(duration);
                    view.startAnimation(scaleOut);

                    Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
                }
            }, delay);
        } else {
            view.setVisibility(View.VISIBLE);
            scaleOut.setDuration(duration);
            view.startAnimation(scaleOut);

            Log.i(TAG, "scale IN effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
        }

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.GONE);
            }
        }, delay + 10);
    }

    public void scaleInOverShoot(final View view, final int delay, final long duration, String handlerName) {
        final ScaleAnimation scaleInOverShoot = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        view.setVisibility(View.INVISIBLE);

        scaleInOverShoot.setInterpolator(new OvershootInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                scaleInOverShoot.setDuration(duration);
                view.startAnimation(scaleInOverShoot);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG, "scale IN OVERSHOOT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);
    }

    public void scaleInOverShoot(final int view_id, final int delay, final long duration, String handlerName, final Activity activity) {
        final ScaleAnimation scaleInOverShoot = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        scaleInOverShoot.setInterpolator(new OvershootInterpolator());

        Map<String, Handler> handlerCreator = new HashMap<>();
        handlerCreator.put(handlerName, new Handler());

        handlerCreator.get(handlerName).postDelayed(new Runnable() {
            @Override
            public void run() {
                View view = activity.findViewById(view_id);
                scaleInOverShoot.setDuration(duration);
                view.startAnimation(scaleInOverShoot);
                view.setVisibility(View.VISIBLE);

                Log.i(TAG, "scale IN OVERSHOOT effect for " + String.valueOf(duration) + "ms with " + String.valueOf(delay) + "ms delay");
            }
        }, delay);
    }

    // Object Animations

    public void moveXYinPX(View view,
                           int fromX, int toX,
                           int durationX, int delayX, TimeInterpolator intX,
                           int fromY, int toY,
                           int durationY, int delayY, TimeInterpolator intY,
                           int duration, int delay) {
        if (Build.VERSION.SDK_INT >= 11) {
            Animator animSet = new AnimatorSet();

            ObjectAnimator animX = ObjectAnimator.ofFloat(view, "x", fromX, toX);
            animX.setDuration(durationX);
            animX.setStartDelay(delayX);
            animX.setInterpolator(intX);

            ObjectAnimator animY = ObjectAnimator.ofFloat(view, "y", fromY, toY);
            animY.setDuration(durationY);
            animY.setStartDelay(delayY);
            animY.setInterpolator(intY);

            animSet.setDuration(duration);
            animSet.setStartDelay(delay);
            animSet.start();
        } else {
            Log.i("ObjectAnimator", "API < 11, can't play animation");
        }
    }

    public void moveXYinPX(int view,
                           int fromX, int toX,
                           int durationX, int delayX, TimeInterpolator intX,
                           int fromY, int toY,
                           int durationY, int delayY, TimeInterpolator intY,
                           int duration, int delay, Activity activity) {

        if (Build.VERSION.SDK_INT >= 11) {
            View object = activity.findViewById(view);

            Animator animSet = new AnimatorSet();

            ObjectAnimator animX = ObjectAnimator.ofFloat(object, "x", fromX, toX);
            animX.setDuration(durationX);
            animX.setStartDelay(delayX);
            animX.setInterpolator(intX);

            ObjectAnimator animY = ObjectAnimator.ofFloat(object, "y", fromY, toY);
            animY.setDuration(durationY);
            animY.setStartDelay(delayY);
            animY.setInterpolator(intY);

            animSet.setDuration(duration);
            animSet.setStartDelay(delay);
            animSet.start();
        } else {
            Log.i("ObjectAnimator", "API < 11, can't play animation");
        }
    }

    public void moveXYinDP(View view,
                           int fromX, int toX,
                           int durationX, int delayX, TimeInterpolator intX,
                           int fromY, int toY,
                           int durationY, int delayY, TimeInterpolator intY,
                           int duration, int delay, Activity activity) {

        if (Build.VERSION.SDK_INT >= 11) {
            float scale = activity.getResources().getDisplayMetrics().density;

            Animator animSet = new AnimatorSet();

            ObjectAnimator animX = ObjectAnimator.ofFloat(view, "x", fromX * scale, toX * scale);
            animX.setDuration(durationX);
            animX.setStartDelay(delayX);
            animX.setInterpolator(intX);

            ObjectAnimator animY = ObjectAnimator.ofFloat(view, "y", fromY * scale, toY * scale);
            animY.setDuration(durationY);
            animY.setStartDelay(delayY);
            animY.setInterpolator(intY);

            animSet.setDuration(duration);
            animSet.setStartDelay(delay);
            animSet.start();
        } else {
            Log.i("ObjectAnimator", "API < 11, can't play animation");
        }
    }

    public void moveXYinDP(int view,
                           int fromX, int toX,
                           int durationX, int delayX, TimeInterpolator intX,
                           int fromY, int toY,
                           int durationY, int delayY, TimeInterpolator intY,
                           int duration, int delay, Activity activity) {

        if (Build.VERSION.SDK_INT >= 11) {
            View object = activity.findViewById(view);

            float scale = activity.getResources().getDisplayMetrics().density;

            Animator animSet = new AnimatorSet();

            ObjectAnimator animX = ObjectAnimator.ofFloat(object, "x", fromX * scale, toX * scale);
            animX.setDuration(durationX);
            animX.setStartDelay(delayX);
            animX.setInterpolator(intX);

            ObjectAnimator animY = ObjectAnimator.ofFloat(object, "y", fromY * scale, toY * scale);
            animY.setDuration(durationY);
            animY.setStartDelay(delayY);
            animY.setInterpolator(intY);

            animSet.setDuration(duration);
            animSet.setStartDelay(delay);
            animSet.start();
        } else {
            Log.i("ObjectAnimator", "API < 11, can't play animation");
        }
    }

    // CircularReveal Animation

    public void circularRevealInPx(int view,
                                   int centerX, int centerY,
                                   int startRad, int endRad, TimeInterpolator interpolator,
                                   int duration, int delay, Activity activity) {

        PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);
        final View object = activity.findViewById(view);

        Log.i(TAG, getViewId(object) + " circular reveal effect for " + duration + "ms with " + delay + "ms delay on (" + centerX + ", " + centerY + "), " + startRad + " > " + endRad);

        if (Build.VERSION.SDK_INT >= 21 && powerManager.isPowerSaveMode() == false) {
            Animator animator = ViewAnimationUtils.createCircularReveal(object, centerX, centerY, startRad, endRad);
            animator.setDuration(duration);
            animator.setStartDelay(delay);
            animator.setInterpolator(interpolator);
            animator.start();

            object.setVisibility(View.VISIBLE);

            if (startRad > endRad) {
                animator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        object.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
            }
        } else {
            Log.i("CircularReveal", "API < 21, No circular reveal used, fade effect used instead.");
            if (startRad < endRad) {
                //this.scaleIn(view, centerX, centerY, delay, duration, "scaleIn", activity);
                fadeIn(view, duration, delay, "circularIn", activity);
            } else {
                //this.scaleOut(view, centerX, centerY, delay, duration, "scaleIn", activity);
                fadeOut(view, duration, delay, activity);
            }
        }
    }

    public Animator circularRevealAnimator(int view,
                                           int centerX, int centerY,
                                           int startRad, int endRad, TimeInterpolator interpolator,
                                           int duration, int delay, Activity activity) {

        final View object = activity.findViewById(view);

        if (Build.VERSION.SDK_INT >= 21) {
            Animator animator = ViewAnimationUtils.createCircularReveal(object, centerX, centerY, startRad, endRad);
            animator.setDuration(duration);
            animator.setStartDelay(delay);
            animator.setInterpolator(interpolator);
            animator.start();

            object.setVisibility(View.VISIBLE);

            if (startRad > endRad) {
                animator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        object.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
            }

            return animator;
        } else {
            Log.i("CircularReveal", "API < 21, No circular reveal used, scale effect used instead.");
            if (startRad < endRad) {
                this.scaleIn(view, centerX, centerY, delay, duration, "scaleIn", activity);
            } else {
                this.scaleOut(view, centerX, centerY, delay, duration, "scaleIn", activity);
            }

            return null;
        }
    }

    public void circularRevealinDP(int view,
                                   int centerX, int centerY,
                                   int startRad, int endRad, TimeInterpolator interpolator,
                                   int duration, int delay, Activity activity) {

        final View object = activity.findViewById(view);

        float scale = activity.getResources().getDisplayMetrics().density;

        if (Build.VERSION.SDK_INT >= 21) {
            Animator animator = ViewAnimationUtils.createCircularReveal(object, centerX * (int) scale, centerY * (int) scale, startRad * (int) scale, endRad * (int) scale);
            animator.setDuration(duration);
            animator.setStartDelay(delay);
            animator.setInterpolator(interpolator);
            animator.start();

            object.setVisibility(View.VISIBLE);

            if (startRad > endRad) {
                animator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        object.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
            }
        } else {
            Log.i("CircularReveal", "API < 21, No circular reveal used, scale effect used instead.");
            if (startRad < endRad) {
                this.scaleIn(view, window.convertDPtoPX(centerX, activity), window.convertDPtoPX(centerY, activity), delay, duration, "scaleIn", activity);
            } else {
                this.scaleOut(view, window.convertDPtoPX(centerX, activity), window.convertDPtoPX(centerY, activity), delay, duration, "scaleIn", activity);
            }
        }
    }

    public void circularRevealTouch(int touch_view, final int reveal_view,
                                    final TimeInterpolator interpolator, final Runnable onClick,
                                    final int duration, final int delay, final Activity activity) {
        View touch = activity.findViewById(touch_view);
        final int coordinate[] = {0, 0};

        touch.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                coordinate[0] = (int) event.getRawX();
                coordinate[1] = (int) event.getRawY();

                return false;
            }
        });

        touch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                circularRevealInPx(reveal_view,
                        coordinate[0], coordinate[1],
                        0, (int) Math.hypot(window.getWindowWidthPx(activity), window.getWindowHeightPx(activity)) + 200, interpolator,
                        duration, delay, activity);
                onClick.run();
            }
        });
    }

    public void circularRevealTouch(View touch_view, final int reveal_view,
                                    final TimeInterpolator interpolator, final Runnable onClick,
                                    final int duration, final int delay, final Activity activity) {
        final int coordinate[] = {0, 0};

        touch_view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                coordinate[0] = (int) event.getRawX();
                coordinate[1] = (int) event.getRawY();

                return false;
            }
        });

        touch_view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                circularRevealInPx(reveal_view,
                        coordinate[0], coordinate[1],
                        0, (int) Math.hypot(window.getWindowWidthPx(activity), window.getWindowHeightPx(activity)) + 200, interpolator,
                        duration, delay, activity);
                onClick.run();
            }
        });
    }
} public class FabHelper {

    public static int FAB = R.id.fab;

    private FloatingActionButton floatingActionButton;

    private AnimateHelper anim = new AnimateHelper();

    public void set(Activity activity) {
        floatingActionButton = (FloatingActionButton)activity.findViewById(FAB);
    }

    public void setColor(int color, Activity activity) {
        try {
            try {
                floatingActionButton.setBackgroundColor(ContextCompat.getColor(activity, color));
            } catch (Exception e) {
                floatingActionButton.setBackgroundColor(color);
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
            Log.e("setFabColor", "Fab is not initialized");
        }
    }

    public void setIcon(int iconRes, Activity activity) {
        floatingActionButton.setImageResource(iconRes);
    }

    public void show() {
        try {
            anim.scaleIn(floatingActionButton, 0, 100, "fabIn");
        } catch (NullPointerException e) {
            Log.i("showFab", "Fab is not initialized");
        }
    }

    public void show(int delay) {
        try {
            anim.scaleIn(floatingActionButton, delay, 100, "fabIn");
        } catch (NullPointerException e) {
            Log.i("showFab", "Fab is not initialized");
        }
    }

    public void show(int delay, int duration) {
        try {
            anim.scaleIn(floatingActionButton, delay, duration, "fabIn");
        } catch (NullPointerException e) {
            Log.i("showFab", "Fab is not initialized");
        }
    }

    public void hide() {
        try {
            anim.scaleOut(floatingActionButton, 0, 100, "fabOut");
        } catch (NullPointerException e) {
            Log.i("hideFab", "Fab is not initialized");
        }
    }

    public void hide(int delay) {
        try {
            anim.scaleOut(floatingActionButton, delay, 100, "fabOut");
        } catch (NullPointerException e) {
            Log.i("hideFab", "Fab is not initialized");
        }
    }

    public void hide(int delay, int duration) {
        try {
            anim.scaleOut(floatingActionButton, delay, duration, "fabOut");
        } catch (NullPointerException e) {
            Log.i("hideFab", "Fab is not initialized");
        }
    }

    public void setVisibility(boolean visible) {
        if (visible) {
            floatingActionButton.setVisibility(View.VISIBLE);
        } else {
            floatingActionButton.setVisibility(View.INVISIBLE);
        }
    }

    public void setScale(double scale) {
        setScaleX((float) scale);
        setScaleY((float) scale);
    }

    public void setScale(float x, float y) {
        setScaleX(x);
        setScaleY(y);
    }

    public void setScaleX(float x) {
        floatingActionButton.setScaleX(x);
    }

    public void setScaleY(float y) {
        floatingActionButton.setScaleY(y);
    }

    public boolean isVisible() {
        if (floatingActionButton != null) {
            return floatingActionButton.getVisibility() == View.VISIBLE;
        } else {
            return false;
        }
    }

    public void setOnClickListener(final Runnable runnable) {
        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runnable.run();
            }
        });
    }
} public class FileHelper {

    public static String PRESET_LOCATION = "http://file.berict.com/tapad/presets";
    public static String PROJECT_LOCATION_PRESETS = Environment.getExternalStorageDirectory().getPath() + "/Tapad/presets";

    private AnimateHelper anim = new AnimateHelper();

    private String TAG = "FileHelper";
    private Decompress decompress;

    public String getStringFromFile(String fileLocation) {
        try {
            FileInputStream inputStream = new FileInputStream(new File(fileLocation));
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
            inputStream.close();
            inputStreamReader.close();
            bufferedReader.close();
            return stringBuilder.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public boolean deleteRecursive(File fileOrDirectory) {
        boolean recursive = true;
        if (fileOrDirectory.isDirectory())
            if (fileOrDirectory.listFiles() != null && fileOrDirectory.listFiles().length > 0)
            for (File child : fileOrDirectory.listFiles())
                recursive = deleteRecursive(child);

        Log.d(TAG, "Deleted : " + fileOrDirectory.toString());
        return fileOrDirectory.delete() && recursive;
    }

    public void unzip(String zipLocation, String targetLocation, String presetName, View parentView, Activity activity, Runnable onFinish) {
        decompress = new Decompress(zipLocation, targetLocation, presetName, parentView, activity, onFinish);
        decompress.execute();
    }

    public void unzip(String zipLocation, String targetLocation, String presetName, Activity activity, Runnable onFinish) {
        decompress = new Decompress(zipLocation, targetLocation, presetName, null, activity, onFinish);
        decompress.execute();
    }

    public void cancelDecompress() {
        if (decompress != null) {
            decompress.cancel(true);
        } else {
            Log.e(TAG, "Decompress is not initialized");
        }
    }

    private boolean isPresetExists(String presetName) {
        // preset exist
        return new File(PROJECT_LOCATION_PRESETS + "/" + presetName).exists(); // folder check
    }

    public long getAvailableExternalMemorySize() {
        return new File(PROJECT_LOCATION_PRESETS).getFreeSpace();
    }

    public boolean isPresetAvailable(Preset preset) {
        // with sound count check
        if (preset != null) {
            String presetName = preset.getTag();
            // preset available
            File folderSound = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/sounds");
            File folderTiming = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/timing");
            File folderAbout = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about");
            File fileJson = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/json");
            File fileAlbum = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/album_art");
            File fileIcon = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/artist_icon");
            File fileImage = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/artist_image");
            if (folderSound.listFiles() != null) {
                Log.d(TAG, "SoundCountPreset = " + preset.getSoundCount() + ", SoundCountFound = " + folderSound.listFiles().length);
            } else {
                Log.e(TAG, "Preset [" + preset.getTag() + "] is not available.");
                return false;
            }
            boolean available = folderSound.isDirectory() && folderSound.exists() &&
                    preset.getSoundCount() == folderSound.listFiles().length &&
                    folderTiming.isDirectory() && folderTiming.exists() &&
                    folderAbout.isDirectory() && folderAbout.exists() &&
                    fileJson.exists() &&
                    fileAlbum.exists() &&
                    fileIcon.exists() &&
                    fileImage.exists();
            if (available) {
                Log.i(TAG, "Preset [" + preset.getTag() + "] is available.");
            }
            return available;
        } else {
            Log.e(TAG, "Preset is null.");
            return false;
        }
    }

    public boolean isPresetAvailable(String presetName) {
        if (presetName != null) {
            // preset available
            File folderSound = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/sounds");
            File folderTiming = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/timing");
            File folderAbout = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about");
            File fileJson = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/json");
            File fileAlbum = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/album_art");
            File fileIcon = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/artist_icon");
            File fileImage = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/artist_image");
            // should be 100%
            return folderSound.isDirectory() && folderSound.exists() &&
                    folderTiming.isDirectory() && folderTiming.exists() &&
                    folderAbout.isDirectory() && folderAbout.exists() &&
                    fileJson.exists() &&
                    fileAlbum.exists() &&
                    fileIcon.exists() &&
                    fileImage.exists();
        } else {
            return false;
        }
    }

    public boolean isPresetMetadataAvailable(String presetName) {
        if (presetName != null) {
            File fileJson = new File(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/json");
            // should be 100%
            return fileJson.exists();
        } else {
            return false;
        }
    }

    public PresetSchema getPresetSchemaFromMetadata(String presetName, Gson gson) {
        if (presetName != null) {
            PresetSchema preset = gson.fromJson(
                    this.getStringFromFile(PROJECT_LOCATION_PRESETS + "/" + presetName + "/about/json"),
                    PresetSchema.class
            );
            preset.getPreset().setTag(presetName);
            return preset;
        } else {
            return null;
        }
    }

    private class Decompress extends AsyncTask<Void, Void, Integer> {

        private String zipLocation;
        private String targetLocation;
        private String presetName;
        private View parentView;
        private Activity activity;
        private Runnable onFinish;

        public Decompress(String zipLocation,
                          String targetLocation,
                          String presetName,
                          View parentView,
                          Activity activity,
                          Runnable onFinish) {
            this.zipLocation = zipLocation;
            this.targetLocation = targetLocation + "/";
            this.presetName = presetName;
            this.activity = activity;
            this.parentView = parentView;
            this.onFinish = onFinish;
            dirChecker("");
        }

        @Override
        protected void onPreExecute() {
            Log.d(TAG, "onPreExecute");
            if (new File(zipLocation).length() > getAvailableExternalMemorySize()) {
                // no storage
                new MaterialDialog.Builder(activity)
                        .title(R.string.preset_store_download_no_space_dialog_title)
                        .content(R.string.preset_store_download_no_space_dialog_text)
                        .contentColorRes(R.color.dark_primary)
                        .neutralText(R.string.dialog_close)
                        .dismissListener(new DialogInterface.OnDismissListener() {
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                                cancelDecompress();
                            }
                        })
                        .show();
            }
        }

        @Override
        protected Integer doInBackground(Void... params) {
            try {
                FileInputStream fileInputStream = new FileInputStream(zipLocation);
                ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
                ZipEntry zipEntry;
                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                    String zipName = zipEntry.getName();
                    Log.d("PresetStore", "Unzipping " + zipName);
                    if (zipEntry.isDirectory()) {
                        dirChecker(zipName);
                    } else {
                        FileOutputStream fileOutputStream = new FileOutputStream(targetLocation + zipName);
                        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                        byte[] buffer = new byte[1024];
                        int read = 0;
                        while ((read = zipInputStream.read(buffer)) != -1) {
                            bufferedOutputStream.write(buffer, 0, read);
                        }
                        bufferedOutputStream.close();
                        zipInputStream.closeEntry();
                        fileOutputStream.close();
                    }
                }
                zipInputStream.close();
                Log.d("PresetStore", "Unzipping completed at " + targetLocation);
            } catch (Exception e) {
                Log.d("PresetStore", "Unzipping failed");
                e.printStackTrace();
            }
            return 0;
            // From https://stackoverflow.com/questions/4504291/how-to-speed-up-unzipping-time-in-java-android/4504692#4504692
        }

        @Override
        protected void onProgressUpdate(Void... args) {
        }

        @Override
        protected void onPostExecute(Integer integer) {
            Log.d(TAG, "onPostExecute");
            super.onPostExecute(integer);
            // finished unzipping, delete the original zip file
            if (parentView != null) {
                // only when downloaded
                if (new File(zipLocation).delete()) {
                    Log.d(TAG, "Successfully removed zip file");
                } else {
                    Log.d(TAG, "Failed to remove zip file");
                }
            }

            if (new File(targetLocation + "/" + presetName).delete()) {
                Log.d(TAG, "Successfully removed zip folder");
            } else {
                Log.d(TAG, "Failed to remove zip folder");
            }

            File newFolder = new File(targetLocation + "/" + presetName);
            File oldFolder = new File(targetLocation + "/preset");
            if (oldFolder.renameTo(newFolder)) {
                Log.d(TAG, "Successfully rename preset folder");
            } else {
                Log.d(TAG, "Failed to rename preset folder");
            }

            // finished downloading preset
            isPresetDownloading = false;
            isPresetChanged = true;

            // refresh the preset adapter actions
            Handler handler = new Handler();
            handler.postDelayed(onFinish, 200);

            if (parentView != null) {
                anim.fadeOut(R.id.layout_preset_store_download_installing, 100, 200, parentView, activity);
                anim.fadeIn(R.id.layout_preset_store_action_layout, 300, 200, "actionIn", parentView, activity);
            }
        }

        @Override
        protected void onCancelled() {
            Log.d(TAG, "DownloadPreset cancelled");
            if (new File(PROJECT_LOCATION_PRESETS + "/" + presetName).delete()) {
                Log.d(TAG, "Successfully removed preset folder");
            } else {
                Log.d(TAG, "Failed to remove preset folder");
            }
            isPresetDownloading = false;
            super.onCancelled();
        }

        private void dirChecker(String dir) {
            File file = new File(targetLocation + dir);

            if (!file.isDirectory()) {
                file.mkdirs();
            }
        }
    }

    public void copy(String sourceLocation, String targetLocation) {
        File sourceFile = new File(sourceLocation);
        File destFile = new File(targetLocation);
        // move file
        if (sourceFile.renameTo(destFile)) {
            Log.d(TAG, "File copied from " + sourceFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
        } else {
            Log.e(TAG, "Failed to copy from  " + sourceFile.getAbsolutePath() + " to " + destFile.getAbsolutePath());
        }
    }
} @SuppressWarnings("unchecked")

public class IntentHelper {
    public void intent(final Activity activity, String name, int delay) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intent");
                    Intent animActivity = new Intent(activity, classToLoad);
                    activity.startActivity(animActivity);
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }
    public void intent(final Activity activity, String name) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Log.i("IntentHelper", "intent");
            Intent animActivity = new Intent(activity, classToLoad);
            activity.startActivity(animActivity);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentWithExtra(final Activity activity, String name, final String extraName, final String extra, int delay) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intent");
                    Intent animActivity = new Intent(activity, classToLoad);
                    animActivity.putExtra(extraName, extra);
                    activity.startActivity(animActivity);
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentWithExtra(final Activity activity, String name, final String extraName, final int extra, int delay) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intent");
                    Intent animActivity = new Intent(activity, classToLoad);
                    animActivity.putExtra(extraName, extra);
                    activity.startActivity(animActivity);
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentAppDetailSettings(final Activity activity, int delay) {
        final Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
        intent.setData(uri);

        if (delay > 0) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intentAppDetailSettings");
                    activity.startActivity(intent);
                }
            }, delay);
        } else {
            Log.i("IntentHelper", "intentAppDetailSettings");
            activity.startActivity(intent);
        }
    }

    public void intentWiFiSettings(final Context context, int delay) {
        try {
            if (delay > 0) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("IntentHelper", "intentWiFiSettings");
                        context.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    }
                }, delay);
            } else {
                Log.i("IntentHelper", "intentWiFiSettings");
                context.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void intentSharedElement(final Activity activity, final String targetName, final int start_element_id, final String transitionName, int delay) {
        final String classname = "com.bedrock.padder." + targetName;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(Build.VERSION.SDK_INT >= 21) {
                        Intent intent = new Intent(activity, classToLoad);
                        View view = activity.findViewById(start_element_id);

                        ActivityOptionsCompat options =
                                ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                                        view,           // The view which starts the transition
                                        transitionName // The transitionName of the view we’re transitioning to
                                );
                        ActivityCompat.startActivity(activity, intent, options.toBundle());
                    } else {
                        intent(activity, targetName);
                    }
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentSharedElementWithExtra(final Activity activity, final String targetName, final int start_element_id, final String transitionName, final String extraName, final int extra, int delay) {
        final String classname = "com.bedrock.padder." + targetName;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(Build.VERSION.SDK_INT >= 21) {
                        Intent intent = new Intent(activity, classToLoad);
                        intent.putExtra(extraName, extra);
                        View view = activity.findViewById(start_element_id);

                        ActivityOptionsCompat options =
                                ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                                        view,           // The view which starts the transition
                                        transitionName // The transitionName of the view we’re transitioning to
                                );
                        ActivityCompat.startActivity(activity, intent, options.toBundle());
                    } else {
                        intentWithExtra(activity, targetName, extraName, extra, 0);
                    }
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentSharedElementWithExtra(final Activity activity, final String targetName, final int start_element_id, final String transitionName, final String extraName, final String extra, int delay) {
        final String classname = "com.bedrock.padder." + targetName;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(Build.VERSION.SDK_INT >= 21) {
                        Intent intent = new Intent(activity, classToLoad);
                        intent.putExtra(extraName, extra);
                        View view = activity.findViewById(start_element_id);

                        ActivityOptionsCompat options =
                                ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                                        view,           // The view which starts the transition
                                        transitionName // The transitionName of the view we’re transitioning to
                                );
                        ActivityCompat.startActivity(activity, intent, options.toBundle());
                    } else {
                        intentWithExtra(activity, targetName, extraName, extra, 0);
                    }
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentSharedElementWithExtra(final Activity activity, final String targetName, final int start_element_id, final String transitionName, final String extraName, final String extra, int delay, final View v) {
        final String classname = "com.bedrock.padder." + targetName;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(Build.VERSION.SDK_INT >= 21) {
                        Intent intent = new Intent(activity, classToLoad);
                        intent.putExtra(extraName, extra);
                        View view = v.findViewById(start_element_id);

                        ActivityOptionsCompat options =
                                ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                                        view,           // The view which starts the transition
                                        transitionName // The transitionName of the view we’re transitioning to
                                );
                        ActivityCompat.startActivity(activity, intent, options.toBundle());
                    } else {
                        intentWithExtra(activity, targetName, extraName, extra, 0);
                    }
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentFlag(final Activity activity, String name, int delay) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intentFlag");
                    Intent animActivity = new Intent(activity, classToLoad);
                    animActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    animActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    activity.startActivity(animActivity);

                    activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentFlagWithExtra(final Activity activity, String name, final String extraName, final String extra, int delay) {
        final String classname = "com.bedrock.padder." + name;
        final Class<Object> classToLoad;
        try{
            classToLoad = (Class<Object>)Class.forName(classname);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("IntentHelper", "intentFlag");
                    Intent animActivity = new Intent(activity, classToLoad);
                    animActivity.putExtra(extraName, extra);
                    animActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    animActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    activity.startActivity(animActivity);

                    activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
                }
            }, delay);
        } catch (ClassNotFoundException e){
            Log.i("IntentHelper", "Error, there is no such class");
        }
    }

    public void intentFinish(final Activity activity, int delay){
        Handler finish = new Handler();
        finish.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i("IntentHelper", "intentFinish");
                activity.overridePendingTransition(R.anim.fade_out, R.anim.fade_in);
                activity.finish();
            }
        }, delay);
    }

    public void intentLink(final Activity activity, String link, int delay) {
        final String url[] = {link};
        if (!link.startsWith("http://") && !link.startsWith("https://")) {
            url[0] = "http://" + link;
        }
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url[0]));
                activity.startActivity(browserIntent);

                activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
            }
        }, delay);
    }

    public void intentShareText(final Activity activity, String subject, String text, final String hint, int delay) {
        final Intent share = new Intent(Intent.ACTION_SEND);
        share.setType("text/plain");
        share.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

        share.putExtra(Intent.EXTRA_SUBJECT, subject);
        share.putExtra(Intent.EXTRA_TEXT, text);

        Handler shareDelay = new Handler();
        shareDelay.postDelayed(new Runnable() {
            @Override
            public void run() {
                activity.startActivity(Intent.createChooser(share, hint));
            }
        }, delay);
    }

    public void intentMarket(final Activity activity, final String appPackage, int delay) {
        Uri uri = Uri.parse("market://details?id=" + appPackage);
        final Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
        // To count with Play market back stack, After pressing back button,
        // to taken back to our application, we need to add following flags to intent.
        if(Build.VERSION.SDK_INT >= 21) {
            goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
                    Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        } else {
            goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        }

        Handler marketDelay = new Handler();
        marketDelay.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    activity.startActivity(goToMarket);
                } catch (ActivityNotFoundException e) {
                    Log.d("ActivityNotFoundExp", "Activity not found, opening in browser");
                    activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + appPackage)));
                }
            }
        }, delay);
    }

    public void intentEmail(final Activity activity, String email_target, String subject, String subjectDesc, String text, String textDesc, final String hint, int delay) {
        String br = System.getProperty("line.separator");
        String info;
        if(textDesc == null || textDesc.equals("")) {
            info = br + br + br + br + "Client : Android [" + BuildConfig.VERSION_NAME + "]";
        } else {
            info = br + br + br + br + "Link : " + textDesc + br + br + "Client : Android [" + BuildConfig.VERSION_NAME + "]";
        }

        final Intent email = new Intent(Intent.ACTION_SEND);
        email.setType("message/rfc822");
        email.putExtra(Intent.EXTRA_EMAIL  , new String[]{email_target});
        email.putExtra(Intent.EXTRA_SUBJECT, subjectDesc + " : " + subject);
        email.putExtra(Intent.EXTRA_TEXT   , text + info);

        Handler emailDelay = new Handler();
        emailDelay.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    activity.startActivity(Intent.createChooser(email, hint));
                } catch (ActivityNotFoundException ex) {
                    Toast.makeText(activity, activity.getResources().getString(R.string.no_email_client), Toast.LENGTH_SHORT).show();
                }
            }
        }, delay);
    }

    public void intentEmail(final Activity activity, int emailTargetId, String subject, String text, int hintResId, int delay) {
        final Intent email = new Intent(Intent.ACTION_SEND);
        final String hint = activity.getResources().getString(hintResId);
        email.setType("message/rfc822");
        email.putExtra(Intent.EXTRA_EMAIL  , new String[]{activity.getResources().getString(emailTargetId)});
        email.putExtra(Intent.EXTRA_SUBJECT, subject);
        email.putExtra(Intent.EXTRA_TEXT   , text);

        Handler emailDelay = new Handler();
        emailDelay.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    activity.startActivity(Intent.createChooser(email, hint));
                } catch (android.content.ActivityNotFoundException ex) {
                    Toast.makeText(activity, activity.getResources().getString(R.string.no_email_client), Toast.LENGTH_SHORT).show();
                }
            }
        }, delay);
    }
} public class ToolbarHelper {

    public static int TOOLBAR = R.id.actionbar_toolbar;
    public static int IMAGE = R.id.actionbar_image;
    
    private ActionBar actionBar;

    public void setActionBar(AppCompatActivity appCompatActivity, View view) {
        appCompatActivity.setSupportActionBar((Toolbar)view.findViewById(TOOLBAR));
        actionBar = appCompatActivity.getSupportActionBar();
    }

    public void setActionBarTitle(int titleResId) {
        if (titleResId == 0) {
            // no title, remove the title
            actionBar.setDisplayShowTitleEnabled(false);
        } else {
            actionBar.setDisplayShowTitleEnabled(true);
            actionBar.setTitle(titleResId);
        }
    }

    public void setActionBarTitle(String title) {
        if (title == null) {
            // no title, remove the title
            actionBar.setDisplayShowTitleEnabled(false);
        } else {
            actionBar.setDisplayShowTitleEnabled(true);
            actionBar.setTitle(title);
        }
    }

    public void setActionBarColor(int color, Activity activity) {
        try {
            try {
                actionBar.setBackgroundDrawable(
                        new ColorDrawable(ContextCompat.getColor(activity, color))
                );
            } catch (Exception e) {
                actionBar.setBackgroundDrawable(
                        new ColorDrawable(color)
                );
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
            Log.e("setActionBar", "Toolbar is not initialized");
        }
    }

    public void setActionBarImage(int imageResId, Activity activity) {
        WindowHelper window = new WindowHelper();
        if (imageResId != 0) {
            ((ImageView) activity.findViewById(IMAGE)).setImageResource(imageResId);
            ((ImageView) activity.findViewById(IMAGE)).setVisibility(View.VISIBLE);
        } else {
            ((ImageView) activity.findViewById(IMAGE)).setVisibility(View.GONE);
        }
    }

    public void setActionBarImage(String imageLocation, Activity activity) {
        WindowHelper window = new WindowHelper();
        ImageView imageView = ((ImageView) activity.findViewById(IMAGE));
        if (imageLocation != null) {
            Picasso.with(activity).load(new File(imageLocation)).into(imageView);
            imageView.setVisibility(View.VISIBLE);
        } else {
            imageView.setVisibility(View.GONE);
        }
    }

    public void setActionBarDisplayHomeAsUp(boolean displayHomeAsUp) {
        actionBar.setDisplayHomeAsUpEnabled(displayHomeAsUp);
    }

    public void setActionBarDisplayHomeAsUpIcon(int iconId) {
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setHomeAsUpIndicator(iconId);
    }

    public ActionBar getActionBar() {
        return actionBar;
    }

    public void setActionBar(AppCompatActivity appCompatActivity) {
        appCompatActivity.setSupportActionBar((Toolbar) appCompatActivity.findViewById(TOOLBAR));
        actionBar = appCompatActivity.getSupportActionBar();
    }

    public void setActionBarPadding(Activity activity) {
        WindowHelper window = new WindowHelper();
        // set the top padding to the status bar size
        Toolbar toolbar = (Toolbar)activity.findViewById(TOOLBAR);
        toolbar.setPadding(0, window.getStatusBarFromPrefs(activity), 0, 0);
    }

    public void setActionBarPadding(Activity activity, View view) {
        WindowHelper window = new WindowHelper();
        // set the top padding to the status bar size
        Toolbar toolbar = (Toolbar)view.findViewById(TOOLBAR);
        toolbar.setPadding(0, window.getStatusBarFromPrefs(activity), 0, 0);
    }

    public void setStatusBarTint(Activity activity) {
        try {
            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
            // enable status bar tint
            tintManager.setStatusBarTintEnabled(true);
            // enable navigation bar tint
            tintManager.setNavigationBarTintEnabled(true);
            // set the transparent color of the status bar, 20% darker
            tintManager.setTintColor(activity.getResources().getColor(R.color.dark_status_bar));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
} public class WindowHelper {

    public void setNavigationBar(int colorId, Activity activity) {
        if (Build.VERSION.SDK_INT >= 16) {
            if (colorId == R.color.transparent) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    Window w = activity.getWindow();
                    w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
                }
                Log.i("WindowHelper", "Transparent navigation bar color applied.");
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    activity.getWindow().setNavigationBarColor(activity.getResources().getColor(colorId));
                    Log.i("WindowHelper", "Navigation bar color applied.");
                }
            }
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 16)");
        }
    }

    public int getNavigationBar(final int id, final Activity activity) {
        /* Must be a parent view */

        final SharedPreferences prefs = activity.getSharedPreferences(APPLICATION_ID, MODE_PRIVATE);
        final int[] navBarHeight = {-1};

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                View view = activity.findViewById(id);
                Rect rect = new Rect();
                view.getGlobalVisibleRect(rect);

                Log.i("Navigation Bar Height", String.valueOf(getWindowHeightPx(activity) + " - " + String.valueOf(rect.bottom) +
                        " = " + String.valueOf(getWindowHeightPx(activity) - rect.bottom)));
                navBarHeight[0] = getWindowHeightPx(activity) - rect.bottom;

                prefs.edit().putInt("navBarPX", navBarHeight[0]).apply();
                Log.i("SharedPrefs", "navBarPX = " + String.valueOf(prefs.getInt("navBarPX", 144)));
            }
        }, 100);

        return navBarHeight[0];
    }

    public int getNavigationBarFromPrefs(Activity activity) {
        int navigationHeight;
        SharedPreferences sharedPreferences = activity.getSharedPreferences(APPLICATION_ID, MODE_PRIVATE);
        navigationHeight = sharedPreferences.getInt("navBarPX", 144);

        if (navigationHeight >= 540 || navigationHeight < 0) {
            // something gone wrong
            navigationHeight = 144;
        }

        return navigationHeight;
    }

    public void setStatusBar(int colorId, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(ContextCompat.getColor(activity, colorId));

            Log.i("WindowHelper", "Status bar color applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public int getStatusBar(final int id, final Activity activity) {
        /* Must be a parent view */

        final SharedPreferences prefs = activity.getSharedPreferences(APPLICATION_ID, MODE_PRIVATE);
        final int[] statBarHeight = {-1};

        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statBarHeight[0] = activity.getResources().getDimensionPixelSize(resourceId);
        }

        if (statBarHeight[0] <= 0) {
            // error with above method
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Rect rectangle = new Rect();
                    Window window = activity.getWindow();
                    window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
                    int statusBar = rectangle.top;
                    Log.i("Status Bar Height", String.valueOf(statusBar));
                    statBarHeight[0] = statusBar;

                    View view = activity.findViewById(id);
                    Rect rect = new Rect();
                    view.getGlobalVisibleRect(rect);

                    Log.i("Status Bar Height", String.valueOf(rect.top));
                    statBarHeight[0] = rect.top;
                }
            }, 10);
        }

        prefs.edit().putInt("statBarPX", statBarHeight[0]).apply();
        Log.i("SharedPrefs", "statBarPX = " + String.valueOf(prefs.getInt("statBarPX", 72)));

        return statBarHeight[0];
    }

    public int getStatusBarFromPrefs(Activity activity) {
        int statusHeight;
        SharedPreferences sharedPreferences = activity.getSharedPreferences(APPLICATION_ID, MODE_PRIVATE);
        statusHeight = sharedPreferences.getInt("statBarPX", 72);

        if (statusHeight >= 240 || statusHeight <= 0) {
            // something gone wrong
            statusHeight = 72;
        }

        return statusHeight;
    }

    public void setVisible(final int viewId, final int delay, final Activity activity) {
        final View view = activity.findViewById(viewId);
        if (view != null) {
            if (delay > 0) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.VISIBLE);
                    }
                }, delay);
            } else {
                view.setVisibility(View.VISIBLE);
            }
        }
    }

    public void setInvisible(final int viewId, final int delay, final Activity activity) {
        final View view = activity.findViewById(viewId);
        if (view != null) {
            if (delay > 0) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.INVISIBLE);
                    }
                }, delay);
            } else {
                view.setVisibility(View.INVISIBLE);
            }
        }
    }

    public void setGone(final int viewId, final int delay, final Activity activity) {
        final View view = activity.findViewById(viewId);
        if (view != null) {
            if (delay > 0) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.setVisibility(View.GONE);
                    }
                }, delay);
            } else {
                view.setVisibility(View.GONE);
            }
        }
    }

    public void setRecentColor(int titleId, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (titleId == 0) {
                // Default app name
                titleId = R.string.app_name;
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_launcher);

            ActivityManager.TaskDescription taskDesc =
                    new ActivityManager.TaskDescription(
                            activity.getResources().getString(titleId),
                            icon,
                            activity.getResources().getColor(R.color.colorPrimary));
            activity.setTaskDescription(taskDesc);

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setRecentColor(int titleId, int color, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (titleId == 0) {
                // Default app name
                titleId = R.string.app_name;
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_launcher);

            // color id - color
            try {
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                activity.getResources().getString(titleId),
                                icon,
                                activity.getResources().getColor(color));
                activity.setTaskDescription(taskDesc);
            } catch (Resources.NotFoundException e) {
                Log.i("NotFoundException", "Handling with normal value");
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                activity.getResources().getString(titleId),
                                icon,
                                color);
                activity.setTaskDescription(taskDesc);
            }

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setRecentColor(int titleId, int iconId, int color, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (titleId == 0) {
                // Default app name
                titleId = R.string.app_name;
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), iconId);

            // color id - color
            try {
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                activity.getResources().getString(titleId),
                                icon,
                                activity.getResources().getColor(color));
                activity.setTaskDescription(taskDesc);
            } catch (Resources.NotFoundException e) {
                Log.i("NotFoundException", "Handling with normal value");
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                activity.getResources().getString(titleId),
                                icon,
                                color);
                activity.setTaskDescription(taskDesc);
            }

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setRecentColor(String title, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (title == null) {
                // Default app name
                title = activity.getResources().getString(R.string.app_name);
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_launcher);

            ActivityManager.TaskDescription taskDesc =
                    new ActivityManager.TaskDescription(
                            title,
                            icon,
                            activity.getResources().getColor(R.color.colorPrimary));
            activity.setTaskDescription(taskDesc);

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setRecentColor(String title, int color, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (title == null) {
                // Default app name
                title = activity.getResources().getString(R.string.app_name);
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_launcher);

            // color id - color
            try {
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                title,
                                icon,
                                activity.getResources().getColor(color));
                activity.setTaskDescription(taskDesc);
            } catch (Resources.NotFoundException e) {
                Log.i("NotFoundException", "Handling with normal value");
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(
                                title,
                                icon,
                                color);
                activity.setTaskDescription(taskDesc);
            }

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setRecentColor(String title, int iconId, int color, Activity activity) {
        if (Build.VERSION.SDK_INT >= 21) {
            if (title == null) {
                // Default app name
                title = activity.getResources().getString(R.string.app_name);
            }

            Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), iconId);

            // color id - color
            try {
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(title, icon, activity.getResources().getColor(color));
                activity.setTaskDescription(taskDesc);
            } catch (Resources.NotFoundException e) {
                Log.i("NotFoundException", "Handling with normal value");
                ActivityManager.TaskDescription taskDesc =
                        new ActivityManager.TaskDescription(title, icon, color);
                activity.setTaskDescription(taskDesc);
            }

            Log.i("WindowHelper", "TaskDescription applied.");
        } else {
            Log.i("WindowHelper", "API doesn't match requirement. (API >= 21)");
        }
    }

    public void setViewBackgroundDrawable(int viewId, int drawableId, Activity activity) {
        View view = activity.findViewById(viewId);

        Drawable drawable;

        if (Build.VERSION.SDK_INT >= 21) {
            drawable = activity.getResources().getDrawable(drawableId, activity.getTheme());
        } else {
            drawable = activity.getResources().getDrawable(drawableId);
        }

        if (Build.VERSION.SDK_INT >= 16) {
            view.setBackground(drawable);
        } else {
            view.setBackgroundDrawable(drawable);
        }

        /** Dammit google, stop deprecating methods! */
    }

    public void setViewBackgroundColor(int viewId, int colorId, Activity activity) {
        try {
            activity.findViewById(viewId).setBackgroundColor(activity.getResources().getColor(colorId));
        } catch (Resources.NotFoundException e) {
            Log.i("NotFoundException", "Handling with normal value");
            activity.findViewById(viewId).setBackgroundColor(colorId);
        }
    }

    public void setViewBackgroundColor(int viewId, int colorId, Activity activity, View view) {
        try {
            view.findViewById(viewId).setBackgroundColor(activity.getResources().getColor(colorId));
        } catch (Resources.NotFoundException e) {
            Log.i("NotFoundException", "Handling with normal value");
            view.findViewById(viewId).setBackgroundColor(colorId);
        }
    }

    public void hideKeyboard(Activity activity) {
        Log.i("HideKeyboard", "Called");
        try {
            InputMethodManager imm = (InputMethodManager) activity.getSystemService(activity.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
        } catch (NullPointerException e) {
            Log.i("HideKeyboard", "NullPointer");
            View view = activity.getCurrentFocus();
            if (view != null) {
                InputMethodManager imm = (InputMethodManager) activity.getSystemService(activity.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
            }
        }
    }

    public int getWindowHeightPx(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        int realHeight;

        if (Build.VERSION.SDK_INT >= 17) {
            //new pleasant way to get real metrics
            DisplayMetrics realMetrics = new DisplayMetrics();
            display.getRealMetrics(realMetrics);
            realHeight = realMetrics.heightPixels;

        } else if (Build.VERSION.SDK_INT >= 14) {
            //reflection for this weird in-between time
            try {
                Method mGetRawH = Display.class.getMethod("getRawHeight");
                realHeight = (Integer) mGetRawH.invoke(display);
            } catch (Exception e) {
                //this may not be 100% accurate, but it's all we've got
                realHeight = display.getHeight();
                Log.e("Display Info", "Couldn't use reflection to get the real display metrics.");
            }

        } else {
            //This should be close, as lower API devices should not have window navigation bars
            realHeight = display.getHeight();
        }
        return realHeight;
    }

    public int getWindowWidthPx(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        int realWidth;

        if (Build.VERSION.SDK_INT >= 17) {
            //new pleasant way to get real metrics
            DisplayMetrics realMetrics = new DisplayMetrics();
            display.getRealMetrics(realMetrics);
            realWidth = realMetrics.widthPixels;

        } else if (Build.VERSION.SDK_INT >= 14) {
            //reflection for this weird in-between time
            try {
                Method mGetRawH = Display.class.getMethod("getRawWidth");
                realWidth = (Integer) mGetRawH.invoke(display);
            } catch (Exception e) {
                //this may not be 100% accurate, but it's all we've got
                realWidth = display.getWidth();
                Log.e("Display Info", "Couldn't use reflection to get the real display metrics.");
            }

        } else {
            //This should be close, as lower API devices should not have window navigation bars
            realWidth = display.getWidth();
        }
        return realWidth;
    }

    public int getWindowHypot(Activity activity) {
        int hypot = (int) Math.hypot(getWindowWidthPx(activity), getWindowHeightPx(activity)) + 200;
        return hypot;
    }

    public int convertPXtoDP(int px, Activity activity) {
        float scale = activity.getResources().getDisplayMetrics().density;

        return (int) (px / scale);
    }

    public int convertDPtoPX(int dp, Activity activity) {
        float scale = activity.getResources().getDisplayMetrics().density;

        return (int) (dp * scale);
    }

    public Rect getRect(int id, Activity activity) {
        View view = activity.findViewById(id);

        Rect rect = new Rect();
        view.getGlobalVisibleRect(rect);

        return rect;
    }

    public static int getBackgroundColor(int id, Activity activity) {
        View view = activity.findViewById(id);
        Drawable drawable = view.getBackground();
        if (drawable instanceof ColorDrawable) {
            ColorDrawable colorDrawable = (ColorDrawable) drawable;
            if (Build.VERSION.SDK_INT >= 11) {
                return colorDrawable.getColor();
            }
            try {
                Field field = colorDrawable.getClass().getDeclaredField("mState");
                field.setAccessible(true);
                Object object = field.get(colorDrawable);
                field = object.getClass().getDeclaredField("mUseColor");
                field.setAccessible(true);
                return field.getInt(object);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    public static int getBackgroundColor(View view) {
        Drawable drawable = view.getBackground();
        if (drawable instanceof ColorDrawable) {
            ColorDrawable colorDrawable = (ColorDrawable) drawable;
            if (Build.VERSION.SDK_INT >= 11) {
                return colorDrawable.getColor();
            }
            try {
                Field field = colorDrawable.getClass().getDeclaredField("mState");
                field.setAccessible(true);
                Object object = field.get(colorDrawable);
                field = object.getClass().getDeclaredField("mUseColor");
                field.setAccessible(true);
                return field.getInt(object);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    public int getColorId(String id) {
        try {
            Class res = R.color.class;
            Field field = res.getField(id);
            return field.getInt(null);
        } catch (Exception e) {
            Log.e("getColorId", "Failure to get color id.", e);
            return -1;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    public int getColorFromString(String colorString) {
        return Color.parseColor(colorString);
    }

    public int getStringId(String id) {
        try {
            Class res = R.string.class;
            Field field = res.getField(id);
            return field.getInt(null);
        } catch (Exception e) {
            Log.e("getStringId", "Failure to get string from id [" + id + "]");
            return -1;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    public static int getId(String id) {
        try {
            Class res = R.id.class;
            Field field = res.getField(id);
            return field.getInt(null);
        } catch (Exception e) {
            Log.e("getId", "Failure to get id.", e);
            return -1;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    @Nullable
    public static String getStringFromId(String id, Context context) {
        try {
            Class res = R.string.class;
            Field field = res.getField(id);
            return context.getResources().getString(field.getInt(null));
        } catch (Exception e) {
            Log.e("getStringFromId", "Failure to get string from id [" + id + "]");
            return null;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    public static String getStringFromIdWithFallback(String id, Context context) {
        try {
            Class res = R.string.class;
            Field field = res.getField(id);
            return context.getResources().getString(field.getInt(null));
        } catch (Exception e) {
            Log.e("getStringFromId", "Failure to get string from id [" + id + "]");
            return id;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    public static String getStringFromId(int resId, Context context) {
        return context.getResources().getString(resId);
    }

    public static View getViewFromId(String id, Activity activity) {
        return activity.findViewById(getId(id));
    }

    public int getDrawableId(String id) {
        try {
            Class res = R.drawable.class;
            Field field = res.getField(id);
            return field.getInt(null);
        } catch (Exception e) {
            Log.e("getDrawableId", "Failure to get drawable with id [" + id + "]");
            return -1;
        }
        //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
    }

    public void setMarginRelativePX(int id, int left, int top, int right, int bottom, Activity activity) {
        View v = activity.findViewById(id);

        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
        params.setMargins(left, top, right, bottom);
        v.setLayoutParams(params);
    }

    public void setMarginRelativeDP(int id, int left, int top, int right, int bottom, Activity activity) {
        View v = activity.findViewById(id);

        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
        params.setMargins(
                convertDPtoPX(left, activity),
                convertDPtoPX(top, activity),
                convertDPtoPX(right, activity),
                convertDPtoPX(bottom, activity));
        v.setLayoutParams(params);
    }

    public void setMarginLinearPX(int id, int left, int top, int right, int bottom, Activity activity) {
        View v = activity.findViewById(id);

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
        params.setMargins(left, top, right, bottom);
        v.setLayoutParams(params);
    }

    public void setMarginLinearDP(int id, int left, int top, int right, int bottom, Activity activity) {
        View v = activity.findViewById(id);

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
        params.setMargins(
                convertDPtoPX(left, activity),
                convertDPtoPX(top, activity),
                convertDPtoPX(right, activity),
                convertDPtoPX(bottom, activity));
        v.setLayoutParams(params);
    }

    private void setButtonPatternDefault(int patternPreset[][][], int btnId, int colorUp, Activity activity) {
        if (btnId >= 0) {
            for (int i = 0; i < patternPreset[btnId].length; i++) {
                for (int j = 0; j < patternPreset[btnId][i].length; j++) {
                    try {
                        activity.findViewById(patternPreset[btnId][i][j]).setBackgroundColor(activity.getResources().getColor(colorUp));
                    } catch (Resources.NotFoundException e) {
                        Log.i("NotFoundException", "Handling with normal value");
                        activity.findViewById(patternPreset[btnId][i][j]).setBackgroundColor(colorUp);
                    }
                }
            }
        }
    }

    public static int getBlendColor(int color0, int color1, float blendPercent, Activity activity) {
        String colorString0 = String.format("#%06X", (0xFFFFFF & getColor(color0, activity)));
        //Log.d("color0", colorString0);
        String colorString1 = String.format("#%06X", (0xFFFFFF & getColor(color1, activity)));
        //Log.d("color1", colorString1);

        int r0 = Integer.parseInt(colorString0.substring(1, 3), 16);
        int g0 = Integer.parseInt(colorString0.substring(3, 5), 16);
        int b0 = Integer.parseInt(colorString0.substring(5, 7), 16);

        int r1 = Integer.parseInt(colorString1.substring(1, 3), 16);
        int g1 = Integer.parseInt(colorString1.substring(3, 5), 16);
        int b1 = Integer.parseInt(colorString1.substring(5, 7), 16);

        String blendColorHex = "#" +
                getTwoDigitHexString(averageIntegerWithPercent(r0, r1, blendPercent)) +
                getTwoDigitHexString(averageIntegerWithPercent(g0, g1, blendPercent)) +
                getTwoDigitHexString(averageIntegerWithPercent(b0, b1, blendPercent));

        return Color.parseColor(blendColorHex);
    }

    public static int averageIntegerWithPercent(int num1, int num2, float percent) {
        return Math.round((num1 - num2) * percent) + num2;
    }

    public static String getTwoDigitHexString(int hexValue) {
        String hexString = Integer.toHexString(hexValue);
        //Log.d("hexStringCheck", hexString);
        if (hexString.length() == 1) {
            hexString = "0" + hexString;
        }
        return hexString;
    }

    public static int getColor(int color, Activity activity) {
        try {
            return activity.getResources().getColor(color);
        } catch (Resources.NotFoundException e) {
            Log.i("NotFoundException", "Handling with normal value");
            return color;
        }
    }

    public void setOnTouch(int id, final Runnable touch, Activity activity) {
        View view = activity.findViewById(id);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                touch.run();
                return false;
            }
        });
    }

    public void setOnClick(int id, final Runnable click, Activity activity) {
        View view = activity.findViewById(id);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                click.run();
            }
        });
    }

    public int getDeviceRam() {
        RandomAccessFile reader = null;
        String load = null;
        double totRam = 0;
        double totRamMb = 0;
        try {
            reader = new RandomAccessFile("/proc/meminfo", "r");
            load = reader.readLine();

            // Get the Number value from the string
            Pattern p = Pattern.compile("(\\d+)");
            Matcher m = p.matcher(load);
            String value = "";
            while (m.find()) {
                value = m.group(1);
                // System.out.println("Ram : " + value);
            }
            reader.close();

            totRam = Double.parseDouble(value);
            // totRam = totRam / 1024;

            totRamMb = totRam / 1024.0;
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        Log.i("getDeviceRam", "Device Ram requested = returned " + String.valueOf(totRamMb));

        return (int) totRamMb;
    }
} public static boolean isPresetVisible = false; public static String PROJECT_LOCATION_PRESETS = Environment.getExternalStorageDirectory().getPath() + "/Tapad/presets"; @Nullable
public static String getStringFromId(String id, Context context) {
    try {
        Class res = R.string.class;
        Field field = res.getField(id);
        return context.getResources().getString(field.getInt(null));
    } catch (Exception e) {
        Log.e("getStringFromId", "Failure to get string from id [" + id + "]");
        return null;
    }
    //from : https://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html
}
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.folderselector.FileChooserDialog;
import com.bedrock.padder.R;
import com.bedrock.padder.fragment.PresetStoreInstalledFragment;
import com.bedrock.padder.fragment.PresetStoreOnlineFragment;
import com.bedrock.padder.fragment.Refreshable;
import com.bedrock.padder.helper.AnimateHelper;
import com.bedrock.padder.helper.FabHelper;
import com.bedrock.padder.helper.FileHelper;
import com.bedrock.padder.helper.IntentHelper;
import com.bedrock.padder.helper.ToolbarHelper;
import com.bedrock.padder.helper.WindowHelper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import static com.bedrock.padder.activity.MainActivity.isPresetVisible;
import static com.bedrock.padder.helper.FileHelper.PROJECT_LOCATION_PRESETS;
import static com.bedrock.padder.helper.WindowHelper.getStringFromId;
package com.bedrock.padder.activity;





public class PresetStoreActivity extends AppCompatActivity implements FileChooserDialog.FileCallback {

    private WindowHelper window = new WindowHelper();
    private AnimateHelper anim = new AnimateHelper();
    private ToolbarHelper toolbar = new ToolbarHelper();
    private IntentHelper intent = new IntentHelper();
    private FabHelper fab = new FabHelper();
    private FileHelper fileHelper = new FileHelper();