public class MainActivity extends UIActivity {

    public static final String BUNDLE_FILE_PATHS = "bundle_file_paths";
    public static final String BUNDLE_URL = "bundle_url";
    public static final String BUNDLE_NAME = "bundle_name";
    public static final String BUNDLE_MD5 = "bundle_md5";

    private static final String SELECTED_ITEM = "SELECTED_ITEM";

    private List<DrawerItem> mItems;
    private IFragment[] mFragments;
    private IFragment mFragment;
    private int mSelectedItem;

    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;

    private AdView mAdView;

    @Override
    public void create(boolean isNew) {

        Context context = getCore().getContext();

        mItems = new ArrayList<DrawerItem>();
        // TODO create selected icons (orange and blue)
        mItems.add(new DrawerItem(context, FragmentInstall.class, R.string.install_title, R.attr.flashIcon, 0));
        mItems.add(new DrawerItem(context, FragmentRules.class, R.string.rules_title, R.attr.acceptIcon, 0));
        mItems.add(new DrawerItem(context, FragmentBackupRestore.class, R.string.backuprestore_title, R.attr.backupRestoreIcon, 0));
        mItems.add(new DrawerItem(context, FragmentRecovery.class, R.string.recovery_fragment_title, R.attr.gridIcon, 0));
        mItems.add(new DrawerItem(context, FragmentGoo.class, R.string.goo_title, R.attr.webIcon, 0));
        mItems.add(new DrawerItem(context, FragmentSettings.class, R.string.settings_title, R.attr.settingsIcon, 0));
        mItems.add(new DrawerItem(context, FragmentAbout.class, R.string.about_title, R.attr.starIcon, 0));

        mFragments = new IFragment[mItems.size()];

        mTitle = mDrawerTitle = getTitle();

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
                GravityCompat.START);
        mDrawerList.setAdapter(new DrawerAdapter(this, mItems));
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.drawable.ic_drawer, R.string.drawer_open,
                R.string.drawer_close) {

            @Override
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu();
            }

            @Override
            public void onDrawerStateChanged(int newState) {
                ((UIPlugin) getCore().getPlugin(Core.PLUGIN_UI)).redraw(mDrawerLayout);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        boolean toInstall = isNew;

        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            String[] filePaths = extras.getStringArray(BUNDLE_FILE_PATHS);
            if (filePaths != null && filePaths.length > 0) {
                FileItemStore.removeItems();
                StoragePlugin sPlugin = (StoragePlugin) getCore().getPlugin(Core.PLUGIN_STORAGE);
                for (String path : filePaths) {
                    sPlugin.addFileItemToStore(path);
                }
                toInstall = true;
            }
            final String url = extras.getString(BUNDLE_URL);
            if (url != null && !url.isEmpty()) {
                final String fileName = extras.getString(BUNDLE_NAME);
                final String md5 = extras.getString(BUNDLE_MD5);
                if (fileName != null && md5 != null) {
                    String message = context.getResources().getString(R.string.new_rom_found_summary,
                            new Object[] { fileName });
                    Dialog.dialog(context, message, R.string.new_rom_found_title, true,
                            R.string.new_version_download, android.R.string.cancel,
                            new OnDialogClosedListener() {

                                @Override
                                public void dialogOk() {
                                    new DownloadFile(getCore(), url, fileName, md5);
                                }

                                @Override
                                public void dialogCancel() {
                                }

                            });
                } else {
                    new DownloadFile(getCore(), url, fileName, md5);
                }
            }
        }

        if (toInstall) {
            selectItem(0);
        }

        mAdView = (AdView) findViewById(R.id.adview);

        LicensePlugin lPlugin = (LicensePlugin) getCore().getPlugin(Core.PLUGIN_LICENSE);
        if (lPlugin.hasProCode()) {
            mAdView.setVisibility(View.GONE);
        } else {
            int resultCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(this);
            if (resultCode != ConnectionResult.SUCCESS) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this, 1);
            }
            mAdView.loadAd(new AdRequest.Builder().build());
            mAdView.setAdListener(new AdListener() {
    
                @Override
                public void onAdClosed() {
                    super.onAdClosed();
                }
    
                @Override
                public void onAdFailedToLoad(int errorCode) {
                    mAdView.loadAd(new AdRequest.Builder().build());
                }
    
                @Override
                public void onAdLeftApplication() {
                    super.onAdLeftApplication();
                }
    
                @Override
                public void onAdLoaded() {
                    super.onAdLoaded();
                }
    
                @Override
                public void onAdOpened() {
                    super.onAdOpened();
                }
                
            });

            Toast.makeText(this, R.string.consider_becoming_a_pro, Toast.LENGTH_LONG).show();

        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (mFragment != null) {
            ((Fragment) mFragment).onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    public void restore(Bundle savedInstanceState) {
        int item = savedInstanceState.getInt(SELECTED_ITEM);
        selectItem(item);
    }

    @Override
    public void save(Bundle outState) {
        outState.putInt(SELECTED_ITEM, mSelectedItem);
    }

    @Override
    public int getContentViewId() {
        return R.layout.activity_main;
    }

    @Override
    public View getMainView() {
        return this.findViewById(R.id.drawer_layout);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        Menus.onPrepareOptionsMenu(menu, mFragment);
        mFragment.onPrepareOptionsMenu(menu);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        mFragment.onOptionsItemSelected(item.getItemId());
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onPause() {
        super.onPause();
        Downloads.cancelAll();
        mAdView.pause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mAdView.destroy();
        getCore().destroy();
    }

    @Override
    public void onResume() {
        super.onResume();
        mAdView.resume();
    }

    public void moveToStart() {
        selectItem(0);
        invalidateOptionsMenu();
    }

    private class DrawerItemClickListener implements
            ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {
        mSelectedItem = position;
        if (position >= 0 && position < mItems.size()) {
            if ((mFragment = mFragments[position]) == null) {
                try {
                    DrawerItem item = mItems.get(position);
                    mFragment = (IFragment) item.getFragmentClass().newInstance();
                    mFragments[position] = mFragment;
                    for (DrawerItem i : mItems) {
                        i.setChecked(i.equals(item));
                    }
                } catch (Exception ex) {
                    // should never get here
                    ex.printStackTrace();
                }
            }
        }
        if (mFragment != null) {
            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.content_frame, (Fragment) mFragment).commit();
        }

        mDrawerList.setItemChecked(position, true);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

} public interface Core extends Serializable {

    public static final String PLUGIN_UI = "UIPlugin";
    public static final String PLUGIN_SUPERUSER = "SuperUserPlugin";
    public static final String PLUGIN_RECOVERY = "RecoveryPlugin";
    public static final String PLUGIN_STORAGE = "StoragePlugin";
    public static final String PLUGIN_REBOOT = "RebootPlugin";
    public static final String PLUGIN_LICENSE = "LicensePlugin";
    public static final String PLUGIN_UPDATE = "UpdatePlugin";

    public interface CoreListener {

        public void pluginStarted(String name);

        public void pluginStopped(String name);

        public void coreMessage(int resId);

        public void coreStarted();

        public void coreStopped();
    }

    public void destroy();

    public boolean isStarted();

    public Context getContext();

    public void setContext(Context context);

    public Plugin getPlugin(String name);

    public Preferences getPreferences();

    public CloudStorage getCloudStorage();

    public void setCloudStorage(int cloudStorage);

    public ONandroid getONandroid();

    public Version getVersion();

    public void moveToInstall();
} public class LicensePlugin extends Plugin {

    private static final String LICENSE_CALLBACK_CLASS = "com.beerbong.zipinst.pro.LicenseCallback";

    private ILicenseCallback mLicenseCallback;
    private boolean mPurchased = false;
    private boolean mPro = false;

    public LicensePlugin(Core core) {
        super(core, Core.PLUGIN_LICENSE);
    }

    @Override
    public void start() {
        try {
            Class<?> pClass = Class.forName(LICENSE_CALLBACK_CLASS);
            mLicenseCallback = (ILicenseCallback) pClass.newInstance();

            mPro = true;

            ((CoreImpl) getCore()).setMessage(R.string.checking_license);

            mLicenseCallback.check(this);

            mPurchased = true;
        } catch (Throwable t) {
            t.printStackTrace();
        }
        started();
    }

    @Override
    public void stop() {
        if (mLicenseCallback != null) {
            mLicenseCallback.destroy();
        }
        stopped();
    }

    public void setPurchased(boolean purchased) {
        mPurchased = purchased;
    }

    public boolean isPurchased() {
        return mPurchased;
    }

    public boolean hasProCode() {
        return mPro;
    }

} public abstract class RecoveryInfo {

    public static final int RECOVERY_CWM = 0;
    public static final int RECOVERY_CWM_BASED = 1;
    public static final int RECOVERY_TWRP = 2;
    public static final int RECOVERY_4EXT = 3;

    private Core mCore;
    private boolean mOldBackup = false;
    private int id;
    private String name = null;
    private String internalSdcard = null;
    private String externalSdcard = null;

    public RecoveryInfo(Core core) {

        mCore = core;

        StoragePlugin rPlugin = (StoragePlugin) core.getPlugin(Core.PLUGIN_STORAGE);
        setExternalSdcard(rPlugin.getExternalStoragePath());
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInternalSdcard() {
        return internalSdcard;
    }

    public void setInternalSdcard(String sdcard) {
        this.internalSdcard = sdcard;
    }

    public String getExternalSdcard() {
        return externalSdcard;
    }

    public void setExternalSdcard(String sdcard) {
        this.externalSdcard = sdcard;
    }

    public abstract String getFullName(Context context);

    public abstract String getFolderPath();

    public abstract String getCommandsFile();

    public abstract String getBackupFolder(String sdcard, boolean force, boolean external);

    public abstract List<String> getCommands(String storage, boolean external, boolean wipeSystem,
            boolean wipeData, boolean wipeCaches, boolean fixPermissions, String backupFolder,
            String backupOptions, String restore) throws Exception;

    protected Core getCore() {
        return mCore;
    }

    public boolean isOldBackup() {
        checkForOldBackup();
        return mOldBackup;
    }

    protected void checkForOldBackup() {
        Preferences prefs = getCore().getPreferences();
        File file = new File("/data/media/clockworkmod/");
        if (prefs.isForceDataMedia()) {
            mOldBackup = true;
        } else {
            mOldBackup = VERSION.SDK_INT >= 16
                    || (file.exists() && file.isDirectory());
        }
    }

} public class RecoveryPlugin extends Plugin {

    private SparseArray<RecoveryInfo> mRecoveries = new SparseArray<RecoveryInfo>();
    private int mInstalledRecovery = -1;
    private String mBootBlock;
    private String mRecoveryBlock;

    public RecoveryPlugin(Core core) {
        super (core, Core.PLUGIN_RECOVERY);
    }

    @Override
    public void start() {
        ((CoreImpl) getCore()).setMessage(R.string.reading_recovery_info);

        (new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {

                Core core = getCore();

                mRecoveries.put(RecoveryInfo.RECOVERY_CWM_BASED, new CwmBasedRecovery(core));
                mRecoveries.put(RecoveryInfo.RECOVERY_CWM, new CwmRecovery(core));
                mRecoveries.put(RecoveryInfo.RECOVERY_TWRP, new TwrpRecovery(core));
                mRecoveries.put(RecoveryInfo.RECOVERY_4EXT, new FourExtRecovery(core));

                SuperUserPlugin suPlugin = (SuperUserPlugin) core.getPlugin(Core.PLUGIN_SUPERUSER);
                suPlugin.run("chmod 777 /cache/recovery/");
                suPlugin.run("chmod 777 /cache/recovery/last_log");

                Preferences prefs = getCore().getPreferences();
                mBootBlock = prefs.getBootBlock();
                mRecoveryBlock = prefs.getRecoveryBlock();

                mInstalledRecovery = testLastLog(new File("/cache/recovery/last_log"), suPlugin, true);

                suPlugin.run("chmod -R 777 /data/media/clockworkmod/");
                suPlugin.run("chmod -R 777 /data/media/clockworkmod/backup/");
                String path = mRecoveries.get(RecoveryInfo.RECOVERY_TWRP).getBackupFolder("sdcard", true,
                        false);
                File file = new File(path);
                suPlugin.run("chmod -R 777 " + file.getAbsolutePath());
                if (file.getParentFile() != null) {
                    suPlugin.run("chmod -R 777 " + file.getParentFile().getAbsolutePath());
                }

                if (mRecoveryBlock != null) {
                    prefs.setRecoveryBlock(mRecoveryBlock);
                }
                if (mBootBlock != null) {
                    prefs.setBootBlock(mBootBlock);
                }

                return (Void) null;
            }

            @Override
            protected void onPostExecute(Void result) {

                Core core = getCore();
                final Preferences prefs = core.getPreferences();
                final Context context = core.getContext();

                if (!prefs.existsRecovery()) {
                    if (mInstalledRecovery != -1) {
                        setRecovery(mInstalledRecovery);
                        started();
                    } else {
                        test(mRecoveries.get(RecoveryInfo.RECOVERY_4EXT), true);
                    }
                } else {
                    if (prefs.isAlertOnChangeRecovery()) {
                        if (mInstalledRecovery != -1 && mInstalledRecovery != getRecovery().getId()) {
                            AlertDialog.Builder alert = new AlertDialog.Builder(context);
                            alert.setTitle(R.string.alert_changed_recovery_title);
                            View view = LayoutInflater.from(context).inflate(R.layout.dialog_changed_recovery,
                                    (ViewGroup) ((Activity) context).findViewById(R.id.changed_recovery_dialog_layout));
                            alert.setView(view);

                            TextView text = (TextView) view.findViewById(R.id.text);
                            text.setText(context.getResources().getString(
                                    R.string.alert_changed_recovery_message,
                                    getRecovery().getFullName(context),
                                    mRecoveries.get(mInstalledRecovery).getFullName(context)));

                            final CheckBox cbDontShow = (CheckBox) view.findViewById(R.id.dontshow);
                            cbDontShow.setChecked(!prefs.isAlertOnChangeRecovery());

                            alert.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog, int whichButton) {
                                    dialog.dismiss();

                                    setRecovery(mInstalledRecovery);
                                    started();

                                    prefs.setAlertOnChangeRecovery(!cbDontShow.isChecked());
                                }
                            });

                            alert.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {

                                public void onClick(DialogInterface dialog, int whichButton) {
                                    dialog.dismiss();

                                    started();

                                    prefs.setAlertOnChangeRecovery(cbDontShow.isChecked());
                                }
                            });

                            alert.show();
                        } else {
                            started();
                        }
                    } else {
                        started();
                    }
                }

            }
        }).execute((Void) null);

    }

    @Override
    public void stop() {
        stopped();
    }

    public boolean hasBootBlock() {
        return mBootBlock != null && !"".equals(mBootBlock);
    }

    public boolean hasRecoveryBlock() {
        return mRecoveryBlock != null && !"".equals(mRecoveryBlock);
    }

    public RecoveryInfo getRecovery() {
        String recovery = getCore().getPreferences().getRecovery();
        for (int i = 0; i < mRecoveries.size(); i++) {
            int key = mRecoveries.keyAt(i);
            RecoveryInfo info = mRecoveries.get(key);
            if (info.getName().equals(recovery)) {
                return info;
            }
        }
        return null;
    }

    public void setRecovery(int id) {
        RecoveryInfo info = mRecoveries.get(id);
        Preferences prefs = getCore().getPreferences();
        prefs.setRecovery(info.getName());
        prefs.setInternalStorage(info.getInternalSdcard());
        prefs.setExternalStorage(info.getExternalSdcard());
    }

    public String getBackupDir(boolean force) {

        RecoveryInfo info = getRecovery();

        Preferences prefs = getCore().getPreferences();
        StoragePlugin sPlugin = (StoragePlugin) getCore().getPlugin(Core.PLUGIN_STORAGE);

        boolean external = sPlugin.hasExternalStorage()
                && prefs.isBackupExternalStorage();
        String sdcard = external ? sPlugin.getExternalStoragePath() : "sdcard";

        return info.getBackupFolder(sdcard, force, external);
    }

    public String[] getBackupList() {

        RecoveryInfo info = getRecovery();

        Preferences prefs = getCore().getPreferences();
        StoragePlugin sPlugin = (StoragePlugin) getCore().getPlugin(Core.PLUGIN_STORAGE);

        boolean external = sPlugin.hasExternalStorage()
                && prefs.isBackupExternalStorage();
        String sdcard = external ? sPlugin.getExternalStoragePath() : "sdcard";

        String folder = info.getBackupFolder(sdcard, true, external);

        List<String> list = new ArrayList<String>();

        if (folder != null && !"".equals(folder)) {
            File f = new File(folder);
            if (f.exists()) {
                File[] fs = f.listFiles();
                for (int i = 0; i < fs.length; i++) {
                    if (fs[i].isDirectory()) {
                        list.add(fs[i].getName());
                    }
                }
            }
        }

        Collections.sort(list, new Comparator<String>() {

            @Override
            public int compare(String s1, String s2) {
                int value = s1.compareTo(s2);
                return -value;
            }
        });

        return list.toArray(new String[list.size()]);
    }

    public String getCommandsFile() {

        RecoveryInfo info = getRecovery();

        return info.getCommandsFile();
    }

    public String[] getCommands(boolean wipeSystem, boolean wipeData, boolean wipeCaches,
            boolean fixPermissions, String backupFolder, String backupOptions, String restore)
            throws Exception {
        List<String> commands = new ArrayList<String>();

        RecoveryInfo info = getRecovery();

        Preferences prefs = getCore().getPreferences();
        String internalStorage = prefs.getInternalStorage();
        while (internalStorage.startsWith("/")) {
            internalStorage = internalStorage.substring(1);
        }

        String externalStorage = prefs.getExternalStorage();
        while (externalStorage.startsWith("/")) {
            externalStorage = externalStorage.substring(1);
        }

        StoragePlugin sPlugin = (StoragePlugin) getCore().getPlugin(Core.PLUGIN_STORAGE);
        boolean external = sPlugin.hasExternalStorage()
                && prefs.isBackupExternalStorage();
        String storage = external ? externalStorage : internalStorage;

        commands.addAll(info.getCommands(storage, external, wipeSystem, wipeData, wipeCaches,
                fixPermissions, backupFolder, backupOptions, restore));

        return commands.toArray(new String[commands.size()]);
    }

    private int testLastLog(File file, SuperUserPlugin suPlugin, boolean retry) {
        int retValue = -1;
        try {
            Scanner scanner = null;
            try {
                scanner = new Scanner(file);
                int lineNumber = 0;
                while ((retValue == -1 || mBootBlock == null || mRecoveryBlock == null) && scanner.hasNext() && lineNumber < 1000) {
                    String line = scanner.nextLine();
                    if (line != null) {
                        if (retValue == -1) {
                            if (line.indexOf("CWM-based Recovery") >= 0) {
                                retValue = RecoveryInfo.RECOVERY_CWM_BASED;
                            } else if (line.indexOf("ClockworkMod Recovery") >= 0) {
                                retValue = RecoveryInfo.RECOVERY_CWM;
                            } else if (line.indexOf("TWRP") >= 0) {
                                retValue = RecoveryInfo.RECOVERY_TWRP;
                            } else if (line.indexOf("4EXT") >= 0) {
                                retValue = RecoveryInfo.RECOVERY_4EXT;
                            }
                        }
                        if (mBootBlock == null) {
                            if (line.indexOf("/boot") >= 0 && line.indexOf("/dev/block/") >= 0) {
                                mBootBlock = line.substring(line.indexOf("/dev/block"));
                                int index = -1;
                                if ((index = mBootBlock.indexOf(" ")) > 0) {
                                    mBootBlock = mBootBlock.substring(0, index);
                                }
                            }
                        }
                        if (mRecoveryBlock == null) {
                            if (line.indexOf("/recovery") >= 0 && line.indexOf("/dev/block/") >= 0) {
                                mRecoveryBlock = line.substring(line.indexOf("/dev/block"));
                                int index = -1;
                                if ((index = mRecoveryBlock.indexOf(" ")) > 0) {
                                    mRecoveryBlock = mRecoveryBlock.substring(0, index);
                                }
                            }
                        }
                    }
                    lineNumber++;
                }
                if (mRecoveryBlock == null) {
                    mRecoveryBlock = "";
                }
                if (mBootBlock == null) {
                    mBootBlock = "";
                }
            } finally {
                if (scanner != null) {
                    scanner.close();
                }
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
            if (retry) {
                suPlugin.run("cp " + file.getAbsolutePath() + " /sdcard/last_log");
                return testLastLog(new File("/sdcard/last_log"), suPlugin, false);
            }
        }
        return retValue;
    }

    private void test(final RecoveryInfo info, boolean first) {

        final Context context = getCore().getContext();
        final String recoveryName = info.getFullName(context);

        if (first) {
            int recNumber = 0;
            File folder = new File(mRecoveries.get(RecoveryInfo.RECOVERY_CWM_BASED).getFolderPath());
            if (folder.exists()) {
                recNumber++;
            }
            folder = new File(mRecoveries.get(RecoveryInfo.RECOVERY_TWRP).getFolderPath());
            if (folder.exists()) {
                recNumber++;
            }
            folder = new File(mRecoveries.get(RecoveryInfo.RECOVERY_4EXT).getFolderPath());
            if (folder.exists()) {
                recNumber++;
            }
            if (recNumber != 1) {
                if (mInstalledRecovery == -1) {
                    selectRecovery(context);
                    return;
                } else {
                    setRecovery(mInstalledRecovery);
                    Toast.makeText(context,
                            context.getString(R.string.recovery_changed, recoveryName),
                            Toast.LENGTH_LONG).show();
                    started();
                    return;
                }
            }
        }

        if (info.getId() == RecoveryInfo.RECOVERY_CWM_BASED) {
            if (mInstalledRecovery == -1) {
                selectRecovery(context);
            } else {
                setRecovery(mInstalledRecovery);
                Toast.makeText(context,
                        context.getString(R.string.recovery_changed, recoveryName),
                        Toast.LENGTH_LONG).show();
                started();
            }
            return;
        }

        File folder = new File(info.getFolderPath());
        if (folder.exists()) {
            AlertDialog.Builder alert = new AlertDialog.Builder(context);
            alert.setCancelable(false);
            alert.setTitle(R.string.recovery_change_alert_title);
            alert.setMessage(context.getString(R.string.recovery_change_alert_message,
                    recoveryName));
            alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int whichButton) {
                    dialog.dismiss();
                    setRecovery(info.getId());
                    Toast.makeText(context,
                            context.getString(R.string.recovery_changed, recoveryName),
                            Toast.LENGTH_LONG).show();
                    started();
                }
            });
            alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();

                    selectRecovery(context);
                }
            });
            alert.show();
        } else {
            switch (info.getId()) {
                case RecoveryInfo.RECOVERY_4EXT:
                    test(mRecoveries.get(RecoveryInfo.RECOVERY_TWRP), false);
                    break;
                case RecoveryInfo.RECOVERY_TWRP:
                    test(mRecoveries.get(RecoveryInfo.RECOVERY_CWM_BASED), false);
                    break;
            }
        }
    }

    private void selectRecovery(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.dialog_recovery, null);

        final RadioGroup mGroup = (RadioGroup) view.findViewById(R.id.recovery_radio_group);

        new AlertDialog.Builder(context).setCancelable(false).setTitle(R.string.recovery_alert_title)
                .setMessage(R.string.recovery_alert_summary).setView(view)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int whichButton) {

                        int id = mGroup.getCheckedRadioButtonId();
                        int recovery = -1;
                        switch (id) {
                            case R.id.cwm :
                                recovery = RecoveryInfo.RECOVERY_CWM;
                                break;
                            case R.id.cwmbased :
                                recovery = RecoveryInfo.RECOVERY_CWM_BASED;
                                break;
                            case R.id.twrp :
                                recovery = RecoveryInfo.RECOVERY_TWRP;
                                break;
                            case R.id.fourext :
                                recovery = RecoveryInfo.RECOVERY_4EXT;
                                break;
                        }

                        setRecovery(recovery);
                        started();

                        dialog.dismiss();
                    }
                }).show();
    }

    public void installBoot(String path) {
        if (mBootBlock == null) {
            return;
        }
        String command = "dd if=" + path + " of=" + mBootBlock;
        SuperUserPlugin suPlugin = (SuperUserPlugin) getCore().getPlugin(Core.PLUGIN_SUPERUSER);
        suPlugin.run(command);
    }

    public void installRecovery(String path) {
        if (mRecoveryBlock == null) {
            return;
        }
        String command = "dd if=" + path + " of=" + mRecoveryBlock;
        SuperUserPlugin suPlugin = (SuperUserPlugin) getCore().getPlugin(Core.PLUGIN_SUPERUSER);
        suPlugin.run(command);
    }

} public class StoragePlugin extends Plugin {

    public static final String ROOT_ID_PRIMARY_EMULATED = "primary";

    private static boolean sScanned = false;

    private String mInternalStoragePath;
    private String mExternalStoragePath;

    public StoragePlugin(Core core) {
        super(core, Core.PLUGIN_STORAGE);
    }

    @Override
    public void start() {
        ((CoreImpl) getCore()).setMessage(R.string.reading_storage_paths);

        (new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {

                if (!sScanned) {
                    sScanned = true;
                    readMounts();
                    mExternalStoragePath = externalStorage();
                }

                return (Void) null;
            }

            @Override
            protected void onPostExecute(Void result) {
                started();
            }
        }).execute((Void) null);
    }

    @Override
    public void stop() {
        stopped();
    }

    public boolean hasExternalStorage() {
        return mExternalStoragePath != null;
//        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

    public boolean isExternalStorage(String path) {
        if (mInternalStoragePath == null) {
            mInternalStoragePath = "/sdcard";
        }
        return !path.startsWith(mInternalStoragePath) && !path.startsWith("/sdcard")
                && !path.startsWith("/mnt/sdcard");
    }

    public String getExternalStoragePath() {
        return mExternalStoragePath;
    }

    public String getInternalStoragePath() {
        return mInternalStoragePath;
    }

    public String getPath(String path) {
        String filePath = new String(path);

        Preferences prefs = getCore().getPreferences();
        String internalStorage = prefs.getInternalStorage();
        String externalStorage = prefs.getExternalStorage();

        String[] internalNames = new String[] {
                mInternalStoragePath,
                "/mnt/sdcard",
                "/storage/sdcard/",
                "/sdcard",
                "/storage/sdcard0",
                "/storage/emulated/0" };
        String[] externalNames = new String[] {
                mExternalStoragePath == null ? " " : mExternalStoragePath,
                "/mnt/extSdCard",
                "/storage/extSdCard/",
                "/extSdCard",
                "/storage/sdcard1",
                "/storage/emulated/1" };
        for (int i = 0; i < internalNames.length; i++) {
            String internalName = internalNames[i];
            String externalName = externalNames[i];
            boolean external = isExternalStorage(filePath);
            if (filePath.endsWith(".sh")) {
                if (!external) {
                    if (filePath.startsWith(internalName)) {
                        if (internalName.endsWith("/")) {
                            filePath = filePath.replace(internalName, "/" + "sdcard" + "/");
                        } else {
                            filePath = filePath.replace(internalName, "/" + "sdcard");
                        }
                        break;
                    }
                }
            } else {
                if (filePath.startsWith(externalName)) {
                    if (externalName.endsWith("/")) {
                        filePath = filePath.replace(externalName, "/" + externalStorage + "/");
                    } else {
                        filePath = filePath.replace(externalName, "/" + externalStorage);
                    }
                    break;
                } else if (filePath.startsWith(internalName)) {
                    if (internalName.endsWith("/")) {
                        filePath = filePath.replace(internalName, "/" + internalStorage + "/");
                    } else {
                        filePath = filePath.replace(internalName, "/" + internalStorage);
                    }
                    break;
                }
            }
        }
        if (filePath.startsWith("//")) {
            filePath = filePath.substring(1);
        }
        return filePath;
    }

    @SuppressWarnings("deprecation")
    public double getSpaceLeft() {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        double sdAvailSize = 0;
        if (Build.VERSION.SDK_INT > 17) {
            sdAvailSize = stat.getAvailableBlocksLong() * stat.getBlockSizeLong();
        } else {
            sdAvailSize = stat.getAvailableBlocks() * stat.getBlockSize();
        }
        // One binary gigabyte equals 1,073,741,824 bytes.
        return sdAvailSize / 1073741824;
    }

    public void addFileItemToStore(String filePath) {

        Context context = getCore().getContext();

        if (filePath == null || (!filePath.endsWith(".zip") && !filePath.endsWith(".sh"))) {
            Toast.makeText(context, R.string.error_file_manager_invalid_zip, Toast.LENGTH_SHORT)
                    .show();
            return;
        }

        if (!filePath.endsWith(".zip") && !filePath.endsWith(".sh")) {
            Toast.makeText(context, R.string.error_file_manager_zip, Toast.LENGTH_SHORT).show();
            return;
        }

        String sdcardPath = new String(filePath);

        filePath = getPath(filePath);

        File file = new File(sdcardPath);
        if (!file.exists()) {
            Toast.makeText(context, R.string.error_file_manager_not_found_zip, Toast.LENGTH_LONG)
                    .show();
        } else {

            FileItemStore.addItem(filePath, sdcardPath, false, getCore().getPreferences()
                    .getZipPosition());
        }
    }

    private void readMounts() {

        Core core = getCore();

        ArrayList<String> mounts = new ArrayList<String>();
        ArrayList<String> vold = new ArrayList<String>();

        Scanner scanner = null;
        try {
            scanner = new Scanner(new File("/proc/mounts"));
            while (scanner.hasNext()) {
                String line = scanner.nextLine();
                if (line.startsWith("/dev/block/vold/")) {
                    String[] lineElements = line.split(" ");
                    String element = lineElements[1];

                    mounts.add(element);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
        boolean addExternal = mounts.size() == 1 && hasExternalStorage();
        if (mounts.size() == 0 || addExternal) {
            mounts.add("/mnt/sdcard");
        }

        File fstab = findFstab(core);
        if (fstab != null) {
            try {
                String path = core.getContext().getExternalCacheDir() + File.separator
                        + fstab.getName();
                SuperUserPlugin suPlugin = (SuperUserPlugin) core.getPlugin(Core.PLUGIN_SUPERUSER);
                suPlugin.run("cp " + fstab.getAbsolutePath() + " " + path);
                suPlugin.run("chmod -R 777 " + path);

                scanner = new Scanner(new File(path));
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("dev_mount")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[2];

                        if (element.contains(":")) {
                            element = element.substring(0, element.indexOf(":"));
                        }

                        if (element.toLowerCase().indexOf("usb") < 0) {
                            vold.add(element);
                        }
                    } else if (line.startsWith("/devices/platform")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[1];

                        if (element.contains(":")) {
                            element = element.substring(0, element.indexOf(":"));
                        }

                        if (element.toLowerCase().indexOf("usb") < 0) {
                            vold.add(element);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (scanner != null) {
                    scanner.close();
                }
            }
        }
        if (addExternal && (vold.size() == 1 && hasExternalStorage())) {
            mounts.add(vold.get(0));
        }
        if (vold.size() == 0 || (vold.size() == 1 && hasExternalStorage())) {
            vold.add("/mnt/sdcard");
        }

        for (int i = 0; i < mounts.size(); i++) {
            String mount = mounts.get(i);
            File root = new File(mount);
            if (!vold.contains(mount)
                    || (!root.exists() || !root.isDirectory() || !root.canWrite())) {
                mounts.remove(i--);
            }
        }

        for (int i = 0; i < mounts.size(); i++) {
            String mount = mounts.get(i);
            if (mount.indexOf("sdcard0") >= 0 || mount.equalsIgnoreCase("/mnt/sdcard")
                    || mount.equalsIgnoreCase("/sdcard")) {
                mInternalStoragePath = mount;
//            } else {
//                mExternalStoragePath = mount;
            }
        }

        if (mInternalStoragePath == null) {
            mInternalStoragePath = "/sdcard";
        }
    }

    private String externalStorage() {
        Context context = getCore().getContext();
        String dirPath = null;
        try {
            String[] volumePaths = null;
            ArrayList<String> volumePathsList = null;
            String path = null;
            if (Build.VERSION.SDK_INT >= 14) {
                volumePaths = volumePaths(context);
                if (volumePaths != null) {
                    volumePathsList = new ArrayList<String>();
                    path = Environment.getExternalStorageDirectory().getAbsolutePath();
                }
            }
            try {
                String primaryVolumePath = primaryVolumePath(context);
                int i = volumePaths.length;
                for (int j = 0;; j++)
                    if (j < i) {
                        String volumePath = volumePaths[j];
                        try {
                            if ((volumePath.equals(System.getenv("EMULATED_STORAGE_SOURCE")))
                                    || (volumePath.equals(System.getenv("EXTERNAL_STORAGE")))
                                    || (volumePath.equals(path))
                                    || (volumePath.equals(primaryVolumePath))
                                    || (volumePath.toLowerCase().contains("usb")))
                                continue;
                            volumePathsList.add(volumePath);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    } else {
                        if (volumePathsList.size() == 1) {
                            dirPath = (String) volumePathsList.get(0);
                        }
                        return dirPath;
                    }
            } catch (Exception ex) {
                ex.printStackTrace();

            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dirPath;
    }

    private String[] volumePaths(Context context) {
        try {
            StorageManager localStorageManager = (StorageManager) context
                    .getSystemService("storage");
            return (String[]) (String[]) localStorageManager.getClass()
                    .getMethod("getVolumePaths", new Class[0])
                    .invoke(localStorageManager, new Object[0]);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private String primaryVolumePath(Context context) {
        try {
            StorageManager localStorageManager = (StorageManager) context
                    .getSystemService("storage");
            Object localObject = localStorageManager.getClass()
                    .getMethod("getPrimaryVolume", new Class[0])
                    .invoke(localStorageManager, new Object[0]);
            return (String) localObject.getClass().getMethod("getPath", new Class[0])
                    .invoke(localObject, new Object[0]);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private File findFstab(Core core) {

        File file = null;

        file = new File("/system/etc/vold.fstab");
        if (file.exists()) {
            return file;
        }

        SuperUserPlugin suPlugin = (SuperUserPlugin) core.getPlugin(Core.PLUGIN_SUPERUSER);
        CommandResult cm = suPlugin
                .run("grep -ls \"/dev/block/\" * --include=fstab.* --exclude=fstab.goldfish");
        if (cm.getOutString() != null) {
            String[] files = cm.getOutString().split("\n");
            for (int i = 0; i < files.length; i++) {
                file = new File(files[i]);
                if (file.exists()) {
                    return file;
                }
            }
        }

        return null;
    }

} public class SuperUserPlugin extends Plugin {

    private static Shell sShell;
    private static boolean sAccess = false;

    public SuperUserPlugin(Core core) {
        super(core, Core.PLUGIN_SUPERUSER);
    }

    @Override
    public void start() {
        ((CoreImpl) getCore()).setMessage(R.string.requesting_su);
        if (sShell == null) {
            sShell = new Shell();
        }
        (new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {
                sAccess = test();
                return (Void) null;
            }

            @Override
            protected void onPostExecute(Void result) {
                if (sAccess) {
                    started();
                } else {
                    Dialog.alert(getCore().getContext(), R.string.alert_no_superuser, new OnDialogClosedListener() {

                        @Override
                        public void dialogOk() {
                            started();
                        }

                        @Override
                        public void dialogCancel() {
                        }
                    });
                }
            }
        }).execute((Void) null);
    }

    @Override
    public void stop() {
        stopped();
    }

    public CommandResult run(String s) {
        return sShell.runWaitFor(s, null);
    }

    public void run(String s, ShellCallback callback) {
        sShell.runWaitFor(s, callback);
    }

    public boolean test() {
        return (sAccess = sShell.test());
    }

    public boolean hasAccess() {
        return sAccess;
    }
} public class RomUpdater implements Updater.UpdaterListener {

    public static final String EXTRA_NOTIFICATION_ID = "NOTIFICATION_ID";
    public static final String EXTRA_NAME = "NAME";
    public static final String EXTRA_URL = "URL";
    public static final String EXTRA_MD5 = "MD5";

    private static final int NOTIFICATION_ID = 122303221;

    private Core mCore;
    private Context mContext;
    private Updater mUpdater;
    private String mRomName;
    private int mRomVersion = -1;
    private boolean mFromAlarm;

    public RomUpdater(Core core) {

        mCore = core;

        mFromAlarm = false;

        mUpdater = getUpdater();

        if (mUpdater != null) {
            mRomName = mUpdater.getRomName();
            mRomVersion = mUpdater.getRomVersion();
        }
    }

    public RomUpdater(Context context) {

        mContext = context;

        mFromAlarm = true;

        mUpdater = getUpdater();

        if (mUpdater != null) {
            mRomName = mUpdater.getRomName();
            mRomVersion = mUpdater.getRomVersion();
        }
    }

    public boolean canUpdate() {
        if (mRomName != null && mRomVersion > 0) {
            return true;
        }
        return false;
    }

    public void check() {
        if (!canUpdate() || mUpdater.isScanning()) {
            return;
        }
        mUpdater.searchVersion();
    }

    @Override
    public void versionFound(RomInfo info) {
        if (info != null && info.version > mRomVersion) {
            if (!mFromAlarm) {
                showNewRomFound(info);
            } else {
                Preferences prefs = new Preferences(mContext);
                if (prefs.isAcceptNotifications()) {
                    showNotification(info);
                }
            }
        } else {
            if (!mFromAlarm) {
                Dialog.toast(mCore.getContext(), R.string.check_rom_updates_no_new);
            }
        }
    }

    @Override
    public void versionError(String error) {
        if (!mFromAlarm) {
            if (error != null) {
                Dialog.toast(
                        mCore.getContext(),
                        mCore.getContext().getResources()
                                .getString(R.string.check_rom_updates_error)
                                + ": " + error);
            } else {
                Dialog.toast(mCore.getContext(), R.string.check_rom_updates_error);
            }
        }
    }

    private void showNewRomFound(final RomInfo info) {
        final Context context = mCore.getContext();
        String message = context.getResources().getString(R.string.new_rom_found_summary,
                new Object[] { info.filename, info.folder });
        try {
            Dialog.dialog(context, message, R.string.new_rom_found_title, true, new OnDialogClosedListener() {
    
                @Override
                public void dialogOk() {
                    ((Activity) context).runOnUiThread(new Runnable() {
    
                        public void run() {
                            new DownloadFile(mCore, info.path, info.filename, info.md5);
                        }
                    });
                }
    
                @Override
                public void dialogCancel() {
                }
    
            });
        } catch (BadTokenException ex) {
            // ignore
        }
    }

    private void showNotification(RomInfo info) {

        Resources resources = mContext.getResources();

        Intent intent = new Intent(mContext, IntroActivity.class);
        intent.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID);
        intent.putExtra(EXTRA_URL, info.path);
        intent.putExtra(EXTRA_NAME, info.filename);
        intent.putExtra(EXTRA_MD5, info.md5);
        PendingIntent pIntent = PendingIntent.getActivity(mContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        Notification.Builder builder = new Notification.Builder(mContext)
                .setContentTitle(resources.getString(R.string.new_rom_found_title))
                .setContentText(
                        resources.getString(R.string.new_rom_name, new Object[] {
                            info.filename
                        }))
                .setSmallIcon(R.drawable.ic_launcher).setContentIntent(pIntent);

        Notification noti = null;
        if (VERSION.SDK_INT > 15) {
            noti = builder.build();
        } else {
            noti = builder.getNotification();
        }

        NotificationManager notificationManager = (NotificationManager) mContext
                .getSystemService(Service.NOTIFICATION_SERVICE);

        noti.flags |= Notification.FLAG_AUTO_CANCEL;

        notificationManager.notify(NOTIFICATION_ID, noti);
    }

    private Updater getUpdater() {
        if (SystemProperties.getProperty(GooUpdater.PROPERTY_GOO_DEVELOPER) != null
                && SystemProperties.getProperty(GooUpdater.PROPERTY_GOO_ROM) != null
                && SystemProperties.getProperty(GooUpdater.PROPERTY_GOO_VERSION) != null) {
            return new GooUpdater(this);
        }
        if (SystemProperties.getProperty(OUCUpdater.PROPERTY_OTA_ID) != null
                && SystemProperties.getProperty(OUCUpdater.PROPERTY_OTA_TIME) != null
                && SystemProperties.getProperty(OUCUpdater.PROPERTY_OTA_VER) != null) {
            return new OUCUpdater(this);
        }
        return null;
    }
} public class SystemProperties {

    private static final int ALARM_ID = 122303221;

    public static String getProperty(String prop) {
        try {
            Process p = Runtime.getRuntime().exec("getprop " + prop);
            p.waitFor();
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = input.readLine();
            return "".equals(line) ? null : line;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }
    
    public static void setAlarm(Context context, long time, boolean trigger) {

        Intent i = new Intent(context, NotificationAlarm.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        PendingIntent pi = PendingIntent
                .getBroadcast(context, ALARM_ID, i, PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.cancel(pi);
        if (time > 0) {
            am.setInexactRepeating(AlarmManager.RTC_WAKEUP, trigger ? 0 : time, time, pi);
        }
    }

    public static boolean alarmExists(Context context) {
        return (PendingIntent.getBroadcast(context, ALARM_ID, new Intent(context,
                NotificationAlarm.class), PendingIntent.FLAG_NO_CREATE) != null);
    }
} public class Preferences {

    public static final String INSTALL_BACKUP = "BACKUP";
    public static final String INSTALL_WIPESYSTEM = "WIPESYSTEM";
    public static final String INSTALL_WIPEDATA = "WIPEDATA";
    public static final String INSTALL_WIPECACHES = "WIPECACHES";
    public static final String INSTALL_FIXPERM = "FIXPERM";
    public static final String[] INSTALL_OPTIONS = {
            INSTALL_BACKUP,
            INSTALL_WIPESYSTEM,
            INSTALL_WIPEDATA,
            INSTALL_WIPECACHES,
            INSTALL_FIXPERM };

    private static final String PROPERTY_FIRST_RUN = "first-run";
    private static final String PROPERTY_INTERNAL_STORAGE = "internal-storage";
    private static final String PROPERTY_EXTERNAL_STORAGE = "external-storage";
    private static final String PROPERTY_FORCE_EXTERNAL_STORAGE = "mountextsdcard";
    private static final String PROPERTY_FORCE_DATA_MEDIA = "forcedatamedia";
    private static final String PROPERTY_BACKUP_EXTERNAL_STORAGE = "backupextsdcard";
    private static final String PROPERTY_RECOVERY = "recovery";
    private static final String PROPERTY_CHANGED_RECOVERY = "changedrecovery";
    private static final String PROPERTY_LIST = "list";
    private static final String PROPERTY_DRAG_AND_DROP = "drag-and-drop";
    private static final String PROPERTY_SHOW_OPTIONS = "show-options";
    private static final String PROPERTY_DARK_THEME = "dark-theme";
    private static final String PROPERTY_CHECK_EXISTS = "check_exists";
    private static final String PROPERTY_CHECK_UPDATES_STARTUP = "check_updates_startup";
    private static final String PROPERTY_DOWNLOAD_PATH = "download_path";
    private static final String PROPERTY_CHECK_MD5 = "check_md5";
    private static final String PROPERTY_OVERRIDE_LIST = "override_list";
    private static final String PROPERTY_AUTOLOAD_LIST = "autoload_list";
    private static final String PROPERTY_ZIP_POSITION = "zip_position";
    private static final String PROPERTY_SPACE_LEFT = "space_left";
    private static final String PROPERTY_SHOW_WIPESYSTEM_ALERT = "wipesystem_alert";
    private static final String PROPERTY_USE_FOLDER = "usefolder";
    private static final String PROPERTY_FOLDER = "folder";
    private static final String PROPERTY_TO_DELETE = "to_delete";
    private static final String PROPERTY_RULES = "rules";
    private static final String PROPERTY_LOGIN = "goologin";
    private static final String PROPERTY_LOGIN_USERNAME = "goologinusername";
    private static final String PROPERTY_CLOUD_STORAGE = "cloudstorage";
    private static final String PROPERTY_DROPBOX_KEY = "dropboxkey";
    private static final String PROPERTY_DROPBOX_SECRET = "dropboxsecret";
    private static final String PROPERTY_LICENSE = "license";
    private static final String PROPERTY_RECOVERY_BLOCK = "recoveryblock";
    private static final String PROPERTY_BOOT_BLOCK = "bootblock";
    private static final String PROPERTY_ENABLE_NOTIFICATIONS = "enable_notifications";
    private static final String PROPERTY_TIME_NOTIFICATIONS = "time_notifications";
    private static final String PROPERTY_USE_ONANDROID = "use_onandroid";

    private static final String DEFAULT_RECOVERY = "cwmbased";
    private static final String DEFAULT_INTERNAL_STORAGE = "emmc";
    private static final String DEFAULT_EXTERNAL_STORAGE = "sdcard";
    private static final String DEFAULT_DOWNLOAD_PATH = "/sdcard/zipinstaller/";
    private static final String DEFAULT_ZIP_POSITION = "last";
    private static final String DEFAULT_TIME_NOTIFICATIONS = "3600000";
    private static final Set<String> DEFAULT_SHOW_OPTIONS = new HashSet<String>();
    private static final String DEFAULT_SPACE_LEFT = "-1";
    private static final int DEFAULT_CLOUD_STORAGE = CloudStorage.STORAGE_NONE;
    private static final boolean DEFAULT_FIRST_RUN = true;
    private static final boolean DEFAULT_CHANGED_RECOVERY = true;
    private static final boolean DEFAULT_FORCE_EXTERNAL_STORAGE = true;
    private static final boolean DEFAULT_FORCE_DATA_MEDIA = VERSION.SDK_INT >= 16;
    private static final boolean DEFAULT_BACKUP_EXTERNAL_STORAGE = false;
    private static final boolean DEFAULT_DRAG_AND_DROP = true;
    private static final boolean DEFAULT_DARK_THEME = false;
    private static final boolean DEFAULT_CHECK_EXISTS = true;
    private static final boolean DEFAULT_CHECK_UPDATES_STARTUP = true;
    private static final boolean DEFAULT_CHECK_MD5 = true;
    private static final boolean DEFAULT_OVERRIDE_LIST = true;
    private static final boolean DEFAULT_AUTOLOAD_LIST = false;
    private static final boolean DEFAULT_ENABLE_NOTIFICATIONS = true;
    private static final boolean DEFAULT_SHOW_WIPESYSTEM_ALERT = true;
    private static final boolean DEFAULT_USE_ONANDROID = false;
    private static final boolean DEFAULT_USE_FOLDER = false;
    private static final String DEFAULT_FOLDER = "/sdcard/download/";

    private Core mCore;
    private Context mContext;
    private SharedPreferences mSettings;

    public Preferences(Core core) {
        this(core.getContext());
        mCore = core;
        mContext = core.getContext();
    }

    public Preferences(Context context) {

        mSettings = PreferenceManager.getDefaultSharedPreferences(context);
        mContext = context;

        DEFAULT_SHOW_OPTIONS.add(INSTALL_BACKUP);
        DEFAULT_SHOW_OPTIONS.add(INSTALL_WIPESYSTEM);
        DEFAULT_SHOW_OPTIONS.add(INSTALL_WIPEDATA);
        DEFAULT_SHOW_OPTIONS.add(INSTALL_WIPECACHES);
        DEFAULT_SHOW_OPTIONS.add(INSTALL_FIXPERM);

        File file = new File(DEFAULT_DOWNLOAD_PATH);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public int getCloudStorage() {
        return mSettings.getInt(PROPERTY_CLOUD_STORAGE, DEFAULT_CLOUD_STORAGE);
    }

    public void setCloudStorage(int value) {
        savePreference(PROPERTY_CLOUD_STORAGE, value);
        mCore.setCloudStorage(value);
    }

    public boolean isFirstRun() {
        return mSettings.getBoolean(PROPERTY_FIRST_RUN, DEFAULT_FIRST_RUN);
    }

    public void setFirstRun(boolean value) {
        savePreference(PROPERTY_FIRST_RUN, value);
    }

    public String getInternalStorage() {
        return mSettings.getString(PROPERTY_INTERNAL_STORAGE, DEFAULT_INTERNAL_STORAGE);
    }

    public void setInternalStorage(String value) {
        savePreference(PROPERTY_INTERNAL_STORAGE, value);
    }

    public String getExternalStorage() {
        return mSettings.getString(PROPERTY_EXTERNAL_STORAGE, DEFAULT_EXTERNAL_STORAGE);
    }

    public void setExternalStorage(String value) {
        savePreference(PROPERTY_EXTERNAL_STORAGE, value);
    }

    public boolean isForceExternalStorage() {
        return mSettings.getBoolean(PROPERTY_FORCE_EXTERNAL_STORAGE, DEFAULT_FORCE_EXTERNAL_STORAGE);
    }

    public void setForceExternalStorage(boolean value) {
        savePreference(PROPERTY_FORCE_EXTERNAL_STORAGE, value);
    }

    public boolean isForceDataMedia() {
        return mSettings.getBoolean(PROPERTY_FORCE_DATA_MEDIA, DEFAULT_FORCE_DATA_MEDIA);
    }

    public void setForceDataMedia(boolean value) {
        savePreference(PROPERTY_FORCE_DATA_MEDIA, value);
    }

    public boolean isBackupExternalStorage() {
        return mSettings.getBoolean(PROPERTY_BACKUP_EXTERNAL_STORAGE, DEFAULT_BACKUP_EXTERNAL_STORAGE);
    }

    public void setBackupExternalStorage(boolean value) {
        savePreference(PROPERTY_BACKUP_EXTERNAL_STORAGE, value);
    }

    public boolean existsRecovery() {
        return mSettings.contains(PROPERTY_RECOVERY);
    }

    public String getRecovery() {
        return mSettings.getString(PROPERTY_RECOVERY, DEFAULT_RECOVERY);
    }

    public void setRecovery(String value) {
        savePreference(PROPERTY_RECOVERY, value);
    }

    public String getList() {
        return mSettings.getString(PROPERTY_LIST, "");
    }

    public void setList(String value) {
        savePreference(PROPERTY_LIST, value);
    }

    public boolean isShowOption(String option) {
        Set<String> options = getShowOptions();
        return options.contains(option);
    }

    public Set<String> getShowOptions() {
        return mSettings.getStringSet(PROPERTY_SHOW_OPTIONS, DEFAULT_SHOW_OPTIONS);
    }

    public void setShowOptions(String options) {
        savePreference(PROPERTY_SHOW_OPTIONS, options);
    }

    public boolean isUseDragAndDrop() {
        return mSettings.getBoolean(PROPERTY_DRAG_AND_DROP, DEFAULT_DRAG_AND_DROP);
    }

    public void setUseDragAndDrop(boolean value) {
        savePreference(PROPERTY_DRAG_AND_DROP, value);
    }

    public boolean isDarkTheme() {
        return mSettings.getBoolean(PROPERTY_DARK_THEME, DEFAULT_DARK_THEME);
    }

    public void setDarkTheme(boolean value) {
        savePreference(PROPERTY_DARK_THEME, value);
    }

    public boolean isAlertOnChangeRecovery() {
        return mSettings.getBoolean(PROPERTY_CHANGED_RECOVERY, DEFAULT_CHANGED_RECOVERY);
    }

    public void setAlertOnChangeRecovery(boolean value) {
        savePreference(PROPERTY_CHANGED_RECOVERY, value);
    }

    public boolean isCheckExists() {
        return mSettings.getBoolean(PROPERTY_CHECK_EXISTS, DEFAULT_CHECK_EXISTS);
    }

    public void setCheckExists(boolean value) {
        savePreference(PROPERTY_CHECK_EXISTS, value);
    }

    public boolean isCheckUpdatesStartup() {
        return mSettings.getBoolean(PROPERTY_CHECK_UPDATES_STARTUP, DEFAULT_CHECK_UPDATES_STARTUP);
    }

    public void setCheckUpdatesStartup(boolean value) {
        savePreference(PROPERTY_CHECK_UPDATES_STARTUP, value);
    }

    public boolean isCheckMD5() {
        return mSettings.getBoolean(PROPERTY_CHECK_MD5, DEFAULT_CHECK_MD5);
    }

    public void setCheckMD5(boolean value) {
        savePreference(PROPERTY_CHECK_MD5, value);
    }

    public boolean isOverrideList() {
        return mSettings.getBoolean(PROPERTY_OVERRIDE_LIST, DEFAULT_OVERRIDE_LIST);
    }

    public void setOverrideList(boolean value) {
        savePreference(PROPERTY_OVERRIDE_LIST, value);
    }

    public boolean isAutoloadList() {
        return mSettings.getBoolean(PROPERTY_AUTOLOAD_LIST, DEFAULT_AUTOLOAD_LIST);
    }

    public void setAutoloadList(boolean value) {
        savePreference(PROPERTY_AUTOLOAD_LIST, value);
    }

    public String getDownloadPath() {
        return mSettings.getString(PROPERTY_DOWNLOAD_PATH, DEFAULT_DOWNLOAD_PATH);
    }

    public void setDownloadPath(String value) {
        if (!value.endsWith("/"))
            value = value + "/";
        savePreference(PROPERTY_DOWNLOAD_PATH, value);
    }

    public boolean isAcceptNotifications() {
        return mSettings.getBoolean(PROPERTY_ENABLE_NOTIFICATIONS, DEFAULT_ENABLE_NOTIFICATIONS);
    }

    public void setAcceptNotifications(boolean value) {
        savePreference(PROPERTY_ENABLE_NOTIFICATIONS, value);
    }

    public long getTimeNotifications() {
        return Long.parseLong(mSettings.getString(PROPERTY_TIME_NOTIFICATIONS,
                DEFAULT_TIME_NOTIFICATIONS));
    }

    public void setTimeNotifications(long value) {
        savePreference(PROPERTY_TIME_NOTIFICATIONS, String.valueOf(value));
    }

    public boolean isUseONandroid() {
        return mSettings.getBoolean(PROPERTY_USE_ONANDROID, DEFAULT_USE_ONANDROID);
    }

    public void setUseONandroid(boolean value) {
        savePreference(PROPERTY_USE_ONANDROID, value);
    }

    public String getZipPosition() {
        return mSettings.getString(PROPERTY_ZIP_POSITION, DEFAULT_ZIP_POSITION);
    }

    public void setZipPosition(String value) {
        savePreference(PROPERTY_ZIP_POSITION, value);
    }

    public double getSpaceLeft() {
        return Double.parseDouble(mSettings.getString(PROPERTY_SPACE_LEFT, DEFAULT_SPACE_LEFT));
    }

    public void setSpaceLeft(double value) {
        savePreference(PROPERTY_SPACE_LEFT, String.valueOf(value));
    }

    public boolean isShowSystemWipeAlert() {
        return mSettings.getBoolean(PROPERTY_SHOW_WIPESYSTEM_ALERT, DEFAULT_SHOW_WIPESYSTEM_ALERT);
    }

    public void setShowSystemWipeAlert(boolean value) {
        savePreference(PROPERTY_SHOW_WIPESYSTEM_ALERT, value);
    }

    public boolean isUseFolder() {
        return mSettings.getBoolean(PROPERTY_USE_FOLDER, DEFAULT_USE_FOLDER);
    }

    public void setUseFolder(boolean value) {
        savePreference(PROPERTY_USE_FOLDER, value);
    }

    public String getFolder() {
        return mSettings.getString(PROPERTY_FOLDER, DEFAULT_FOLDER);
    }

    public void setFolder(String value) {
        savePreference(PROPERTY_FOLDER, value);
    }

    public String[] getToDelete() {
        return getArrayProperty(PROPERTY_TO_DELETE);
    }

    public void setToDelete(String[] value) {
        setArrayProperty(PROPERTY_TO_DELETE, value);
    }

    public List<Rule> getRules() {
        return Rule.createRulesAsList(mContext, mSettings.getString(PROPERTY_RULES, ""));
    }

    public void setRules(List<Rule> rules) {
        savePreference(PROPERTY_RULES, Rule.storeRules(rules));
    }

    public void addRule(String name, int type) {
        List<Rule> rules = getRules();
        List<Rule> newRules = new ArrayList<Rule>();
        for (Rule rule : rules) {
            newRules.add(rule);
        }
        newRules.add(new Rule(mContext, name, type));
        savePreference(PROPERTY_RULES, Rule.storeRules(newRules));
    }

    public void removeRule(int index) {
        List<Rule> rules = getRules();
        rules.remove(index);
        savePreference(PROPERTY_RULES, Rule.storeRules(rules));
    }

    public String getRecoveryBlock() {
        return mSettings.getString(PROPERTY_RECOVERY_BLOCK, null);
    }

    public void setRecoveryBlock(String value) {
        savePreference(PROPERTY_RECOVERY_BLOCK, value);
    }

    public String getBootBlock() {
        return mSettings.getString(PROPERTY_BOOT_BLOCK, null);
    }

    public void setBootBlock(String value) {
        savePreference(PROPERTY_BOOT_BLOCK, value);
    }

    public void logout() {
        savePreference(PROPERTY_LOGIN, "");
    }

    public void login(String value) {
        savePreference(PROPERTY_LOGIN, value);
    }

    public void setLoginUserName(String value) {
        savePreference(PROPERTY_LOGIN_USERNAME, value);
    }

    public boolean isLogged() {
        return !"".equals(mSettings.getString(PROPERTY_LOGIN, ""));
    }

    public String getLogin() {
        return mSettings.getString(PROPERTY_LOGIN, "");
    }

    public String getLoginUserName() {
        return mSettings.getString(PROPERTY_LOGIN_USERNAME, null);
    }

    public void setDropboxKey(String value) {
        savePreference(PROPERTY_DROPBOX_KEY, value);
    }

    public String getDropboxKey() {
        return mSettings.getString(PROPERTY_DROPBOX_KEY, null);
    }

    public void setDropboxSecret(String value) {
        savePreference(PROPERTY_DROPBOX_SECRET, value);
    }

    public String getDropboxSecret() {
        return mSettings.getString(PROPERTY_DROPBOX_SECRET, null);
    }

    public void setLicense(boolean value) {
        savePreference(PROPERTY_LICENSE, value);
    }

    public boolean getLicense() {
        return mSettings.getBoolean(PROPERTY_LICENSE, false);
    }

    private String[] getArrayProperty(String property) {
        String value = mSettings.getString(property, "");
        String[] array = value.split("\n");
        if (array.length == 1 && "".equals(array[0])) {
            return new String[0];
        }
        return array;
    }

    public void setArrayProperty(String property, String[] value) {
        String array = "";
        for (int i = 0; i < value.length; i++) {
            array += value[i] + "\n";
        }
        savePreference(property, array);
    }

    private void savePreference(String preference, String value) {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putString(preference, value);
        editor.commit();
    }

    private void savePreference(String preference, boolean value) {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putBoolean(preference, value);
        editor.commit();
    }

    private void savePreference(String preference, int value) {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putInt(preference, value);
        editor.commit();
    }
} public class FileItemStore {

    public interface FileItemStoreListener {

        public void storeChanged();
    }

    private static FileItemStoreListener sListener;
    private static List<FileItem> sList = new ArrayList<FileItem>();

    public static void setFileItemStoreListener(FileItemStoreListener listener) {
        sListener = listener;
    }

    public static int size() {
        return sList.size();
    }

    public static List<FileItem> getItems() {
        return sList;
    }

    public static String[] getPaths() {
        String[] paths = new String[sList.size()];
        int i = 0;
        for (FileItem item : sList) {
            paths[i] = item.getPath();
            i++;
        }
        return paths;
    }

    public static FileItem getItem(int i) {
        return sList.get(i);
    }

    public static void addItem(String realPath, String sdcardPath, boolean delete, String zipPosition) {

        sList.remove(realPath);

        FileItem item = new FileItem(realPath, sdcardPath.substring(sdcardPath.lastIndexOf("/") + 1),
                sdcardPath, delete);

        if ("first".equals(zipPosition)) {
            sList.add(0, item);
        } else {
            sList.add(item);
        }

        if (sListener != null) {
            sListener.storeChanged();
        }
    }

    public static void removeItems() {
        sList.clear();
        if (sListener != null) {
            sListener.storeChanged();
        }
    }

    public static void removeItem(String key) {
        int size = size(), i = 0;
        for (; i < size; i++) {
            if (key.equals(sList.get(i).getKey())) {
                sList.remove(i);
                return;
            }
        }
        if (sListener != null) {
            sListener.storeChanged();
        }
    }

    public static void move(int from, int to) {
        if (from == to)
            return;
        FileItem toMove = sList.get(from);
        while (sList.indexOf(toMove) != to) {
            int i = sList.indexOf(toMove);
            Collections.swap(sList, i, to < from ? i - 1 : i + 1);
        }
        if (sListener != null) {
            sListener.storeChanged();
        }
    }

    private FileItemStore() {
    }
} public abstract class UIPreferenceFragment extends PreferenceFragment implements IFragment, UIInterface {

    private Core mCore;

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

        mCore = CoreFactory.getCore();

        ((UIPlugin) mCore.getPlugin(Core.PLUGIN_UI)).registerUI(this);

        addPreferencesFromResource(getContentViewId());

        create(savedInstanceState == null);

        getActivity().setTitle(getTitle());

        if (savedInstanceState != null) {
            restore(savedInstanceState);
        }

        redraw();
    }

    public abstract int getTitle();

    @Override
    public void setTheme(int resid) {
    }

    @Override
    public void redraw() {
        ((UIPlugin) mCore.getPlugin(Core.PLUGIN_UI)).redraw(this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        save(outState);
    }

    @Override
    public View getMainView(View rootView) {
        return getMainView();
    }

    @Override
    public View getMainView() {
        return getView();
    }

    protected Core getCore() {
        return mCore;
    }

    @Override
    public void onOptionsItemSelected(int id) {
    }

} public class FolderPicker extends Dialog implements OnItemClickListener, OnClickListener {

    private ListView mFolders;
    private TextView mCurrentFolder;
    private Folder mPath;
    private Folder mFilePath;
    private File mRoot;
    private FolderAdapter mAdapter;
    private OnClickListener mListener;
    private boolean mAcceptFiles;
    private View mOkButton;
    private String[] mFileExtensions;
    private Drawable[] mFileDrawables;

    public FolderPicker(Context context, OnClickListener listener, String defaultFolder) {
        this(context, listener, defaultFolder, null, null, false);
    }

    public FolderPicker(Context context, OnClickListener listener, String defaultFolder,
            String[] fileExtensions, Drawable[] fileDrawables, boolean acceptFiles) {
        super(context);
        mListener = listener;
        mAcceptFiles = acceptFiles;
        mFileExtensions = fileExtensions;
        mFileDrawables = fileDrawables;
        setTitle(acceptFiles ? R.string.pick_file : R.string.pick_folder);
        setContentView(R.layout.picker_folders);

        mRoot = new File("/");

        mOkButton = findViewById(R.id.ok_btn);
        mOkButton.setOnClickListener(this);
        findViewById(R.id.cancel_btn).setOnClickListener(this);
        mCurrentFolder = (TextView) findViewById(R.id.current_folder);
        mCurrentFolder.setSelected(true);
        mFolders = (ListView) findViewById(R.id.folders);
        mFolders.setOnItemClickListener(this);

        mAdapter = new FolderAdapter();
        mFolders.setAdapter(mAdapter);
        if (defaultFolder != null) {
            mPath = new Folder(defaultFolder);
        }
        if (mPath == null || !mPath.exists()) {
            mPath = new Folder(Environment.getExternalStorageDirectory().getAbsolutePath());
        }
        updateAdapter();
    }

    public String getPath() {
        if (!mAcceptFiles) {
            return mPath.getAbsolutePath();
        } else if (mFilePath != null) {
            return mFilePath.getAbsolutePath();
        } else {
            return null;
        }
    }

    public void onClick(View v) {
        if (v == mOkButton && mListener != null) {
            mListener.onClick(this, DialogInterface.BUTTON_POSITIVE);
        }
        dismiss();
    }

    private void updateAdapter() {
        mCurrentFolder.setText(mPath.getAbsolutePath());
        mAdapter.clear();
        if (!mPath.equals(mRoot)) {
            mAdapter.add(new Folder(mPath, true));
        }
        File[] dirs = mPath.listFiles(mDirFilter);
        Arrays.sort(dirs);
        for (int i = 0; i < dirs.length; i++) {
            mAdapter.add(new Folder(dirs[i]));
        }
        if (mAcceptFiles) {
            File[] files = mPath.listFiles(mFileFilter);
            Arrays.sort(files);
            for (int i = 0; i < files.length; i++) {
                if (mFileExtensions == null) {
                    mAdapter.add(new Folder(files[i]));
                } else {
                    for (int j=0;j<mFileExtensions.length;j++) {
                        if (files[i].getName().endsWith(mFileExtensions[j])) {
                            mAdapter.add(new Folder(files[i],
                                    mFileDrawables != null ? mFileDrawables[j] : null));
                        }
                    }
                }
            }
        }
        mAdapter.notifyDataSetChanged();
        mFolders.setSelection(0);
        mFolders.startLayoutAnimation();
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mAcceptFiles) {
            Folder item = (Folder) mAdapter.getItem(position);
            if (item.isDirectory()) {
                mPath = item;
                updateAdapter();
                mFilePath = null;
            } else {
                mCurrentFolder.setText(item.getAbsolutePath());
                mFilePath = item;
                mListener.onClick(this, DialogInterface.BUTTON_POSITIVE);
                dismiss();
            }
        } else {
            mPath = (Folder) mAdapter.getItem(position);
            updateAdapter();
        }
    }

    private FileFilter mDirFilter = new FileFilter() {

        public boolean accept(File file) {
            return file.isDirectory();
        }
    };

    private FileFilter mFileFilter = new FileFilter() {

        public boolean accept(File file) {
            return file.isFile();
        }
    };

    class FolderAdapter extends BaseAdapter {

        ArrayList<Folder> mFolders = new ArrayList<Folder>();
        LayoutInflater mInflater = LayoutInflater.from(getContext());
        private Drawable mFileDrawable;
        private Drawable mFolderDrawable;

        public FolderAdapter() {
            TypedArray ta = getContext().getTheme().obtainStyledAttributes(new int[] {R.attr.fileIcon});
            mFileDrawable = ta.getDrawable(0);
            ta.recycle();
            ta = getContext().getTheme().obtainStyledAttributes(new int[] {R.attr.folderIcon});
            mFolderDrawable = ta.getDrawable(0);
            ta.recycle();
        }

        public int getCount() {
            return mFolders.size();
        }

        public void add(Folder folder) {
            mFolders.add(folder);
        }

        public void clear() {
            mFolders.clear();
        }

        public Object getItem(int position) {
            return mFolders.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            View v = mInflater.inflate(R.layout.picker_folder, parent, false);
            Folder folder = mFolders.get(position);
            TextView name = (TextView) v.findViewById(R.id.folder_name);

            Drawable drawable = null;
            if (folder.isParent) {
                name.setText("[..]");
                drawable = mFolderDrawable;
            } else {
                name.setText(folder.getName());
                if (folder.isDirectory()) {
                    drawable = mFolderDrawable;
                } else if (folder.drawable != null) {
                    drawable = folder.drawable;
                } else {
                    drawable = mFileDrawable;
                }
            }
            if (VERSION.SDK_INT > 15) {
                v.findViewById(R.id.folder_icon).setBackground(drawable);
            } else {
                v.findViewById(R.id.folder_icon).setBackgroundDrawable(drawable);
            }
            return v;
        }
    }

    @SuppressWarnings("serial")
    class Folder extends File {

        protected Drawable drawable;
        protected boolean isParent;

        public Folder(File file) {
            super(file.getAbsolutePath());
        }

        public Folder(File file, Drawable drawable) {
            super(file.getAbsolutePath());
            this.drawable = drawable;
        }

        public Folder(File file, boolean unused) {
            super(file.getParent() == null ? "/" : file.getParent());
            isParent = true;
        }

        public Folder(String path) {
            super(path);
        }
    }
}
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.beerbong.zipinst.MainActivity;
import com.beerbong.zipinst.R;
import com.beerbong.zipinst.core.Core;
import com.beerbong.zipinst.core.plugins.license.LicensePlugin;
import com.beerbong.zipinst.core.plugins.recovery.RecoveryInfo;
import com.beerbong.zipinst.core.plugins.recovery.RecoveryPlugin;
import com.beerbong.zipinst.core.plugins.storage.StoragePlugin;
import com.beerbong.zipinst.core.plugins.superuser.SuperUserPlugin;
import com.beerbong.zipinst.core.plugins.update.RomUpdater;
import com.beerbong.zipinst.io.SystemProperties;
import com.beerbong.zipinst.preferences.Preferences;
import com.beerbong.zipinst.store.FileItemStore;
import com.beerbong.zipinst.ui.UIPreferenceFragment;
import com.beerbong.zipinst.ui.widget.FolderPicker;
/*
 * Copyright 2014 ZipInstaller Project
 *
 * This file is part of ZipInstaller.
 *
 * ZipInstaller is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ZipInstaller is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ZipInstaller.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.beerbong.zipinst.fragment;



public class FragmentSettings extends UIPreferenceFragment implements OnPreferenceChangeListener {

    private static final String PREFERENCE_CATEGORY_RECOVERY = "settings_recovery";
    private static final String PREFERENCE_CATEGORY_UPDATE = "settings_update";
    private static final String PREFERENCE_RECOVERY = "recovery";
    private static final String PREFERENCE_INTERNAL_SDCARD = "internalsdcard";
    private static final String PREFERENCE_EXTERNAL_SDCARD = "externalsdcard";
    private static final String PREFERENCE_FORCE_EXTERNAL_SDCARD = "mountextsdcard";
    private static final String PREFERENCE_FORCE_DATA_MEDIA = "forcedatamedia";
    private static final String PREFERENCE_BACKUP_EXTERNAL_SDCARD = "backupextsdcard";
    private static final String PREFERENCE_DAD = "draganddrop";
    private static final String PREFERENCE_DARK_THEME = "darktheme";
    private static final String PREFERENCE_CHECK_EXISTS = "checkexists";
    private static final String PREFERENCE_CHECK_UPDATE_STARTUP = "updateonstartup";
    private static final String PREFERENCE_CHECK_MD5 = "checkmd5";
//    private static final String PREFERENCE_OVERRIDE_LIST = "overridelist";
//    private static final String PREFERENCE_AUTOLOAD_LIST = "autoloadlist";
    private static final String PREFERENCE_DOWNLOAD_PATH = "downloadpath";
    private static final String PREFERENCE_ZIP_POSITION = "zipposition";
    private static final String PREFERENCE_OPTIONS = "show-options";
    private static final String PREFERENCE_SPACE_LEFT = "spaceleft";
    private static final String PREFERENCE_SYSTEMWIPE_ALERT = "wipesystemalert";
    private static final String PREFERENCE_USE_FOLDER = "usefolder";
    private static final String PREFERENCE_FOLDER = "folder";
    private static final String PREFERENCE_CHECK_ROOT = "checkroot";
    private static final String PREFERENCE_TIME_NOTIFICATIONS = "time_notifications";
    private static final String PREFERENCE_CHECK_ROM_UPDATES = "check_rom_updates";

    private Preference mRecovery;
    private Preference mInternalSdcard;
    private Preference mExternalSdcard;
    private CheckBoxPreference mForceExternalSdcard;
    private CheckBoxPreference mForceDataMedia;
    private CheckBoxPreference mBackupExternalSdcard;
    private CheckBoxPreference mDad;
    private CheckBoxPreference mDarkTheme;
    private CheckBoxPreference mCheckExists;
    private CheckBoxPreference mCheckMd5;
    //    private CheckBoxPreference mOverrideList;
    //    private CheckBoxPreference mAutoloadList;
    private CheckBoxPreference mSystemWipeAlert;
    private CheckBoxPreference mUpdatesOnStartup;
    private Preference mDownloadPath;
    private ListPreference mZipPosition;
    private MultiSelectListPreference mOptions;
    private ListPreference mSpaceLeft;
    private CheckBoxPreference mUseFolder;
    private Preference mFolder;
    private Preference mCheckRom;
    private ListPreference mCheckTime;

    private RomUpdater mRomUpdater;

    @Override
    public int getContentViewId() {
        return R.layout.fragment_settings;
    }

    @Override
    public void create(boolean isNew) {

        mRecovery = findPreference(PREFERENCE_RECOVERY);
        mInternalSdcard = findPreference(PREFERENCE_INTERNAL_SDCARD);
        mExternalSdcard = findPreference(PREFERENCE_EXTERNAL_SDCARD);
        mForceExternalSdcard = (CheckBoxPreference) findPreference(PREFERENCE_FORCE_EXTERNAL_SDCARD);
        mForceDataMedia = (CheckBoxPreference) findPreference(PREFERENCE_FORCE_DATA_MEDIA);
        mBackupExternalSdcard = (CheckBoxPreference) findPreference(PREFERENCE_BACKUP_EXTERNAL_SDCARD);
        mDad = (CheckBoxPreference) findPreference(PREFERENCE_DAD);
        mDarkTheme = (CheckBoxPreference) findPreference(PREFERENCE_DARK_THEME);
        mCheckExists = (CheckBoxPreference) findPreference(PREFERENCE_CHECK_EXISTS);
        mCheckMd5 = (CheckBoxPreference) findPreference(PREFERENCE_CHECK_MD5);
        //        mOverrideList = (CheckBoxPreference) findPreference(PREFERENCE_OVERRIDE_LIST);
        //        mAutoloadList = (CheckBoxPreference) findPreference(PREFERENCE_AUTOLOAD_LIST);
        mDownloadPath = findPreference(PREFERENCE_DOWNLOAD_PATH);
        mZipPosition = (ListPreference) findPreference(PREFERENCE_ZIP_POSITION);
        mOptions = (MultiSelectListPreference) findPreference(PREFERENCE_OPTIONS);
        mSpaceLeft = (ListPreference) findPreference(PREFERENCE_SPACE_LEFT);
        mSystemWipeAlert = (CheckBoxPreference) findPreference(PREFERENCE_SYSTEMWIPE_ALERT);
        mUpdatesOnStartup = (CheckBoxPreference) findPreference(PREFERENCE_CHECK_UPDATE_STARTUP);
        mUseFolder = (CheckBoxPreference) findPreference(PREFERENCE_USE_FOLDER);
        mFolder = findPreference(PREFERENCE_FOLDER);
        mCheckRom = findPreference(PREFERENCE_CHECK_ROM_UPDATES);
        mCheckTime = (ListPreference) findPreference(PREFERENCE_TIME_NOTIFICATIONS);

        Preferences prefs = getCore().getPreferences();

        mForceExternalSdcard.setChecked(prefs.isForceExternalStorage());
        mForceDataMedia.setChecked(prefs.isForceDataMedia());
        mBackupExternalSdcard.setChecked(prefs.isBackupExternalStorage());
        mDad.setChecked(prefs.isUseDragAndDrop());
        mDarkTheme.setChecked(prefs.isDarkTheme());
        mCheckExists.setChecked(prefs.isCheckExists());
        mCheckMd5.setChecked(prefs.isCheckMD5());
//        mOverrideList.setChecked(prefs.isOverrideList());
//        mAutoloadList.setChecked(prefs.isAutoloadList());
        mZipPosition.setValue(prefs.getZipPosition());
        mZipPosition.setOnPreferenceChangeListener(this);
        mOptions.setValues(prefs.getShowOptions());
        mSpaceLeft.setValue(String.valueOf(prefs.getSpaceLeft()));
        mSpaceLeft.setOnPreferenceChangeListener(this);
        mSystemWipeAlert.setChecked(prefs.isShowSystemWipeAlert());
        mUseFolder.setChecked(prefs.isUseFolder());
        mUpdatesOnStartup.setChecked(prefs.isCheckUpdatesStartup());
        mCheckTime.setValue(String.valueOf(prefs.getTimeNotifications()));

        mRomUpdater = new RomUpdater(getCore());

        StoragePlugin sPlugin = (StoragePlugin) getCore().getPlugin(Core.PLUGIN_STORAGE);