public class WallpaperDetailsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<WallpaperProperty> mProperties;
    private ColorPalette mPalette;
    private List<Category> mCategories;
    private final Context mContext;

    private static final int TYPE_DETAILS = 0;
    private static final int TYPE_PALETTE_HEADER = 1;
    private static final int TYPE_PALETTE = 2;
    private static final int TYPE_CATEGORY = 3;

    public WallpaperDetailsAdapter(@NonNull Context context,
                                   @NonNull List<WallpaperProperty> properties,
                                   @NonNull ColorPalette palette,
                                   @NonNull List<Category> categories) {
        mContext = context;
        mProperties = properties;
        mPalette = palette;
        mCategories = categories;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_DETAILS) {
            View view = LayoutInflater.from(mContext).inflate(
                    R.layout.activity_wallpaper_preview_details, parent, false);
            return new PropertyViewHolder(view);
        } else if (viewType == TYPE_PALETTE_HEADER) {
            View view = LayoutInflater.from(mContext).inflate(
                    R.layout.activity_wallpaper_preview_palette_header, parent, false);
            return new PaletteHeaderViewHolder(view);
        } else if (viewType == TYPE_PALETTE) {
            View view = LayoutInflater.from(mContext).inflate(
                    R.layout.activity_wallpaper_preview_palette, parent, false);
            return new PaletteViewHolder(view);
        }

        View view = LayoutInflater.from(mContext).inflate(
                R.layout.activity_wallpaper_preview_category, parent, false);
        return new CategoryViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        try {
            if (holder.itemView != null) {
                StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams)
                        holder.itemView.getLayoutParams();
                layoutParams.setFullSpan(getItemViewType(position) == TYPE_PALETTE_HEADER ||
                        getItemViewType(position) == TYPE_CATEGORY);
            }
        } catch (Exception e) {
            LogUtil.e(Log.getStackTraceString(e));
        }

        if (holder.getItemViewType() == TYPE_DETAILS) {
            PropertyViewHolder propertyViewHolder = (PropertyViewHolder) holder;

            WallpaperProperty property = mProperties.get(position);
            propertyViewHolder.title.setText(property.getTitle());
            if (property.getIcon() != 0) {
                int color = ColorHelper.getAttributeColor(mContext, android.R.attr.textColorSecondary);
                Drawable drawable = DrawableHelper.getTintedDrawable(mContext, property.getIcon(), color);
                propertyViewHolder.title.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
            }
        } else if (holder.getItemViewType() == TYPE_PALETTE_HEADER) {
            PaletteHeaderViewHolder paletteHeaderViewHolder = (PaletteHeaderViewHolder) holder;

            paletteHeaderViewHolder.container.setVisibility(View.VISIBLE);
            if (mPalette.size() <= 0) {
                paletteHeaderViewHolder.container.setVisibility(View.GONE);
            }
        } else if (holder.getItemViewType() == TYPE_PALETTE) {
            PaletteViewHolder paletteViewHolder = (PaletteViewHolder) holder;

            int finalPosition = position - mProperties.size() - 1;
            paletteViewHolder.title.setText(mPalette.getHex(finalPosition));

            Drawable drawable = DrawableHelper.getTintedDrawable(mContext,
                    R.drawable.ic_toolbar_details_palette_color, mPalette.get(finalPosition));
            paletteViewHolder.title.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
        } else if (holder.getItemViewType() == TYPE_CATEGORY) {
            CategoryViewHolder categoryViewHolder = (CategoryViewHolder) holder;

            categoryViewHolder.container.setVisibility(View.VISIBLE);
            if (mCategories.size() == 0) {
                categoryViewHolder.container.setVisibility(View.GONE);
                return;
            }

            categoryViewHolder.recyclerView.setAdapter(new WallpaperDetailsCategoryAdapter(mContext, mCategories));
            int spanCount = mContext.getResources().getInteger(R.integer.wallpaper_details_column_count);
            ViewHelper.resetSpanCount(categoryViewHolder.recyclerView, spanCount);
        }
    }

    @Override
    public int getItemCount() {
        return mProperties.size() + mPalette.size() + 2;
    }

    @Override
    public int getItemViewType(int position) {
        if (position < mProperties.size()) {
            return TYPE_DETAILS;
        } else if (position == mProperties.size()) {
            return TYPE_PALETTE_HEADER;
        } else if (position > mProperties.size() && position < (getItemCount() - 1)) {
            return TYPE_PALETTE;
        }
        return TYPE_CATEGORY;
    }

    class PropertyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        @BindView(R2.id.title)
        TextView title;

        PropertyViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            title.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            int position = getAdapterPosition();
            if (position < 0 || position > mProperties.size()) return;

            showCafeBar(mProperties.get(position).getDesc(), "", false);
        }
    }

    class PaletteHeaderViewHolder extends RecyclerView.ViewHolder {

        @BindView(R2.id.container)
        LinearLayout container;

        PaletteHeaderViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

            TextView title = itemView.findViewById(R.id.title);
            int color = ColorHelper.getAttributeColor(mContext, android.R.attr.textColorPrimary);
            Drawable drawable = DrawableHelper.getTintedDrawable(mContext,
                    R.drawable.ic_toolbar_details_palette, color);
            title.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
        }
    }

    class PaletteViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        @BindView(R2.id.title)
        TextView title;

        PaletteViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            title.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            int position = getAdapterPosition() - mProperties.size() - 1;
            if (position < 0 || position > mPalette.size()) return;

            String content = mContext.getResources().getString(R.string.wallpaper_property_color,
                    mPalette.getHex(position));
            showCafeBar(content, mPalette.getHex(position), true);
        }
    }

    class CategoryViewHolder extends RecyclerView.ViewHolder {

        @BindView(R2.id.title)
        TextView title;
        @BindView(R2.id.recyclerview)
        RecyclerView recyclerView;
        @BindView(R2.id.container)
        LinearLayout container;

        CategoryViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

            int color = ColorHelper.getAttributeColor(mContext, android.R.attr.textColorPrimary);
            Drawable drawable = DrawableHelper.getTintedDrawable(mContext,
                    R.drawable.ic_toolbar_details_category, color);
            title.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);

            recyclerView.setItemAnimator(new DefaultItemAnimator());
            recyclerView.setLayoutManager(new GridLayoutManager(mContext,
                    mContext.getResources().getInteger(R.integer.wallpaper_details_column_count)));
            recyclerView.setNestedScrollingEnabled(false);
        }
    }

    private void showCafeBar(String title, String content, boolean showCopy) {
        CafeBar.Builder builder = CafeBar.builder(mContext)
                .theme(Preferences.get(mContext).isDarkTheme() ? CafeBarTheme.LIGHT : CafeBarTheme.DARK)
                .typeface(TypefaceHelper.getRegular(mContext), TypefaceHelper.getBold(mContext))
                .content(title)
                .floating(true);

        if (showCopy) {
            builder.neutralText(R.string.copy)
                    .onNeutral(cafeBar -> {
                        ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
                        ClipData clip = ClipData.newPlainText("content", content);
                        clipboard.setPrimaryClip(clip);
                    });
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            boolean tabletMode = mContext.getResources().getBoolean(R.bool.android_helpers_tablet_mode);
            if (!tabletMode && mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
               builder.fitSystemWindow();
            }
        }

        CafeBar cafeBar = builder.build();
        cafeBar.show();
    }

    public void setWallpaperProperties(@NonNull List<WallpaperProperty> properties) {
        mProperties = properties;
        notifyDataSetChanged();
    }

    public void setColorPalette(@NonNull ColorPalette palette) {
        mPalette = palette;
        notifyDataSetChanged();
    }

    public void setCategories(@NonNull List<Category> categories) {
        mCategories = categories;
        notifyDataSetChanged();
    }
}
 public abstract class WallpaperBoardApplication extends Application implements ApplicationCallback {

    public static boolean sIsClickable = true;
    private static boolean mIsLatestWallpapersLoaded;
    private static WallpaperBoardConfiguration mConfiguration;

    private Thread.UncaughtExceptionHandler mHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        Database.get(this).openDatabase();
        Preferences.get(this);

        if (!ImageLoader.getInstance().isInited())
            ImageLoader.getInstance().init(ImageConfig.getImageLoaderConfiguration(this));

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                .setDefaultFontPath("fonts/Font-Regular.ttf")
                .setFontAttrId(R.attr.fontPath)
                .build());

        //Enable logging
        LogUtil.setLoggingTag(getString(R.string.app_name));
        LogUtil.setLoggingEnabled(true);

        mConfiguration = onInit();

        if (mConfiguration.isCrashReportEnabled()) {
            String[] urls = getResources().getStringArray(R.array.about_social_links);
            boolean isContainsValidEmail = false;
            for (String url : urls) {
                if (UrlHelper.getType(url) == UrlHelper.Type.EMAIL) {
                    isContainsValidEmail = true;
                    mConfiguration.setCrashReportEmail(url);
                    break;
                }
            }

            if (isContainsValidEmail) {
                mHandler = Thread.getDefaultUncaughtExceptionHandler();
                Thread.setDefaultUncaughtExceptionHandler(this::handleUncaughtException);
            } else {
                mConfiguration.setCrashReportEnabled(false);
                mConfiguration.setCrashReportEmail(null);
            }
        }

        LocaleHelper.setLocale(this);
    }

    public static WallpaperBoardConfiguration getConfig() {
        if (mConfiguration == null) {
            mConfiguration = new WallpaperBoardConfiguration();
        }
        return mConfiguration;
    }

    public static boolean isLatestWallpapersLoaded() {
        return mIsLatestWallpapersLoaded;
    }

    public static void setLatestWallpapersLoaded(boolean loaded) {
        mIsLatestWallpapersLoaded = loaded;
    }

    private void handleUncaughtException(Thread thread, Throwable throwable) {
        try {
            StringBuilder sb = new StringBuilder();
            SimpleDateFormat dateFormat = TimeHelper.getDefaultShortDateTimeFormat();
            String dateTime = dateFormat.format(new Date());
            sb.append("Crash Time : ").append(dateTime).append("\n");
            sb.append("Class Name : ").append(throwable.getClass().getName()).append("\n");
            sb.append("Caused By : ").append(throwable.toString()).append("\n");

            for (StackTraceElement element : throwable.getStackTrace()) {
                sb.append("\n");
                sb.append(element.toString());
            }

            Intent intent = new Intent(this, WallpaperBoardCrashReport.class);
            intent.putExtra(WallpaperBoardCrashReport.EXTRA_STACKTRACE, sb.toString());
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            startActivity(intent);
        } catch (Exception e) {
            if (mHandler != null) {
                mHandler.uncaughtException(thread, throwable);
                return;
            }
        }
        System.exit(1);
    }
}
 public class Database extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "wallpaper_board_database";
    private static final int DATABASE_VERSION = 5;

    private static final String TABLE_WALLPAPERS = "wallpapers";
    private static final String TABLE_CATEGORIES = "categories";

    private static final String KEY_URL = "url";
    private static final String KEY_THUMB_URL = "thumbUrl";
    private static final String KEY_MIME_TYPE = "mimeType";
    private static final String KEY_SIZE = "size";
    private static final String KEY_COLOR = "color";
    private static final String KEY_WIDTH = "width";
    private static final String KEY_HEIGHT = "height";
    private static final String KEY_COUNT = "count";

    public static final String KEY_ID = "id";
    public static final String KEY_NAME = "name";
    public static final String KEY_AUTHOR = "author";
    public static final String KEY_CATEGORY = "category";

    private static final String KEY_FAVORITE = "favorite";
    private static final String KEY_SELECTED = "selected";
    private static final String KEY_MUZEI_SELECTED = "muzeiSelected";
    private static final String KEY_ADDED_ON = "addedOn";

    private final Context mContext;

    private static WeakReference<Database> mDatabase;
    private SQLiteDatabase mSQLiteDatabase;
    private static List<String> mFavoriteUrlsBackup;

    public static Database get(@NonNull Context context) {
        if (mDatabase == null || mDatabase.get() == null) {
            mDatabase = new WeakReference<>(new Database(context));
        }
        return mDatabase.get();
    }

    private Database(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_TABLE_CATEGORY = "CREATE TABLE " +TABLE_CATEGORIES+ "(" +
                KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                KEY_NAME + " TEXT NOT NULL," +
                KEY_SELECTED + " INTEGER DEFAULT 1," +
                KEY_MUZEI_SELECTED + " INTEGER DEFAULT 1, " +
                "UNIQUE (" +KEY_NAME+ "))";
        String CREATE_TABLE_WALLPAPER = "CREATE TABLE IF NOT EXISTS " +TABLE_WALLPAPERS+ "(" +
                KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                KEY_NAME+ " TEXT NOT NULL, " +
                KEY_AUTHOR + " TEXT, " +
                KEY_URL + " TEXT NOT NULL, " +
                KEY_THUMB_URL + " TEXT NOT NULL, " +
                KEY_MIME_TYPE + " TEXT, " +
                KEY_SIZE + " INTEGER DEFAULT 0, " +
                KEY_COLOR + " INTEGER DEFAULT 0, " +
                KEY_WIDTH + " INTEGER DEFAULT 0, " +
                KEY_HEIGHT + " INTEGER DEFAULT 0, " +
                KEY_CATEGORY + " TEXT NOT NULL," +
                KEY_FAVORITE + " INTEGER DEFAULT 0," +
                KEY_ADDED_ON + " TEXT NOT NULL, " +
                "UNIQUE (" +KEY_URL+ "))";
        db.execSQL(CREATE_TABLE_CATEGORY);
        db.execSQL(CREATE_TABLE_WALLPAPER);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        /*
         * Need to clear shared preferences with version 1.5.0b-3
         */
        if (newVersion == 5) {
            Preferences.get(mContext).clearPreferences();
        }
        resetDatabase(db);
    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        resetDatabase(db);
    }

    private void resetDatabase(SQLiteDatabase db) {
        List<String> tables = new ArrayList<>();
        Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type=\'table\'", null);
        if (cursor.moveToFirst()) {
            do {
                tables.add(cursor.getString(0));
            } while (cursor.moveToNext());
        }
        cursor.close();

        mFavoriteUrlsBackup = new ArrayList<>();
        cursor = db.query(TABLE_WALLPAPERS, new String[]{KEY_URL}, KEY_FAVORITE +" = ?",
                new String[]{"1"}, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                mFavoriteUrlsBackup.add(cursor.getString(0));
            } while (cursor.moveToNext());
        }
        cursor.close();

        for (int i = 0; i < tables.size(); i++) {
            try {
                String dropQuery = "DROP TABLE IF EXISTS " + tables.get(i);
                if (!tables.get(i).equalsIgnoreCase("SQLITE_SEQUENCE"))
                    db.execSQL(dropQuery);
            } catch (Exception ignored) {}
        }
        onCreate(db);
    }

    public void restoreFavorites() {
        if (mFavoriteUrlsBackup == null) return;

        for (String url : mFavoriteUrlsBackup) {
            ContentValues values = new ContentValues();
            values.put(KEY_FAVORITE, 1);
            mDatabase.get().mSQLiteDatabase.update(TABLE_WALLPAPERS,
                    values, KEY_URL +" = ?", new String[]{url});
        }

        mFavoriteUrlsBackup.clear();
        mFavoriteUrlsBackup = null;
    }

    public boolean openDatabase() {
        try {
            if (mDatabase == null || mDatabase.get() == null) {
                LogUtil.e("Database error: openDatabase() database instance is null");
                return false;
            }

            if (mDatabase.get().mSQLiteDatabase == null) {
                mDatabase.get().mSQLiteDatabase = mDatabase.get().getWritableDatabase();
            }

            if (!mDatabase.get().mSQLiteDatabase.isOpen()) {
                LogUtil.e("Database error: database openable false, trying to open the database again");
                mDatabase.get().mSQLiteDatabase = mDatabase.get().getWritableDatabase();
            }
            return mDatabase.get().mSQLiteDatabase.isOpen();
        } catch (SQLiteException | NullPointerException e) {
            LogUtil.e(Log.getStackTraceString(e));
            return false;
        }
    }

    public boolean closeDatabase() {
        try {
            if (mDatabase == null || mDatabase.get() == null) {
                LogUtil.e("Database error: closeDatabase() database instance is null");
                return false;
            }

            if (mDatabase.get().mSQLiteDatabase == null) {
                LogUtil.e("Database error: trying to close database which is not opened");
                return false;
            }
            mDatabase.get().mSQLiteDatabase.close();
            return true;
        } catch (SQLiteException | NullPointerException e) {
            LogUtil.e(Log.getStackTraceString(e));
            return false;
        }
    }

    public void add(@NonNull List<?> categoryLIst, @NonNull List<?> wallpaperList) {
        if (!openDatabase()) {
            LogUtil.e("Database error: add() failed to open database");
            return;
        }

        Iterator categoryIterator = categoryLIst.iterator();
        Iterator wallpaperIterator = wallpaperList.iterator();
        int size = categoryLIst.size() > wallpaperList.size() ? categoryLIst.size() : wallpaperList.size();

        String categoryQuery = "INSERT OR IGNORE INTO " +TABLE_CATEGORIES+ " (" +KEY_NAME+ ") VALUES (?);";
        String wallpaperQuery = "INSERT OR IGNORE INTO " +TABLE_WALLPAPERS+ " (" +KEY_NAME+ "," +KEY_AUTHOR+ "," +KEY_URL+ ","
                +KEY_THUMB_URL+ "," +KEY_CATEGORY+ "," +KEY_ADDED_ON+ ") VALUES (?,?,?,?,?,?);";

        SQLiteStatement categoryStatements = mDatabase.get().mSQLiteDatabase.compileStatement(categoryQuery);
        SQLiteStatement wallpaperStatements = mDatabase.get().mSQLiteDatabase.compileStatement(wallpaperQuery);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        int i = 0;
        do {
            categoryStatements.clearBindings();
            wallpaperStatements.clearBindings();

            if (categoryIterator.hasNext()) {
                Category category;
                if (categoryIterator.next() instanceof Category) {
                    category = (Category) categoryLIst.get(i);
                } else {
                    category = JsonHelper.getCategory(categoryLIst.get(i));
                }

                if (category != null) {
                    categoryStatements.bindString(1, category.getName());
                    categoryStatements.execute();
                }
            }

            if (wallpaperIterator.hasNext()) {
                Wallpaper wallpaper;
                if (wallpaperIterator.next() instanceof Wallpaper) {
                    wallpaper = (Wallpaper) wallpaperList.get(i);
                } else {
                    wallpaper = JsonHelper.getWallpaper(wallpaperList.get(i));
                }

                if (wallpaper != null) {
                    if (wallpaper.getUrl() != null) {
                        String name = wallpaper.getName();
                        if (name == null) name = "";

                        wallpaperStatements.bindString(1, name);

                        if (wallpaper.getAuthor() != null) {
                            wallpaperStatements.bindString(2, wallpaper.getAuthor());
                        } else {
                            wallpaperStatements.bindNull(2);
                        }

                        wallpaperStatements.bindString(3, wallpaper.getUrl());
                        wallpaperStatements.bindString(4, wallpaper.getThumbUrl());
                        wallpaperStatements.bindString(5, wallpaper.getCategory());
                        wallpaperStatements.bindString(6, TimeHelper.getLongDateTime());
                        wallpaperStatements.execute();
                    }
                }
            }
            i++;
        } while (i < size);

        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void addCategories(List<?> list) {
        if (!openDatabase()) {
            LogUtil.e("Database error: addCategories() failed to open database");
            return;
        }

        String query = "INSERT OR IGNORE INTO " +TABLE_CATEGORIES+ " (" +KEY_NAME+ ") VALUES (?);";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (int i = 0; i < list.size(); i++) {
            statement.clearBindings();

            Category category;
            if (list.get(i) instanceof Category) {
                category = (Category) list.get(i);
            } else {
                category = JsonHelper.getCategory(list.get(i));
            }

            if (category != null) {
                statement.bindString(1, category.getName());
                statement.execute();
            }
        }
        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void addWallpapers(@NonNull List<?> list) {
        if (!openDatabase()) {
            LogUtil.e("Database error: addWallpapers() failed to open database");
            return;
        }

        String query = "INSERT OR IGNORE INTO " +TABLE_WALLPAPERS+ " (" +KEY_NAME+ "," +KEY_AUTHOR+ "," +KEY_URL+ ","
                +KEY_THUMB_URL+ "," +KEY_CATEGORY+ "," +KEY_ADDED_ON+ ") VALUES (?,?,?,?,?,?);";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (int i = 0; i < list.size(); i++) {
            statement.clearBindings();

            Wallpaper wallpaper;
            if (list.get(i) instanceof Wallpaper) {
                wallpaper = (Wallpaper) list.get(i);
            } else {
                wallpaper = JsonHelper.getWallpaper(list.get(i));
            }

            if (wallpaper != null) {
                if (wallpaper.getUrl() != null) {
                    String name = wallpaper.getName();
                    if (name == null) name = "";

                    statement.bindString(1, name);

                    if (wallpaper.getAuthor() != null) {
                        statement.bindString(2, wallpaper.getAuthor());
                    } else {
                        statement.bindNull(2);
                    }

                    statement.bindString(3, wallpaper.getUrl());
                    statement.bindString(4, wallpaper.getThumbUrl());
                    statement.bindString(5, wallpaper.getCategory());
                    statement.bindString(6, TimeHelper.getLongDateTime());
                    statement.execute();
                }
            }
        }
        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void updateWallpaper(Wallpaper wallpaper) {
        if (!openDatabase()) {
            LogUtil.e("Database error: updateWallpaper() failed to open database");
            return;
        }

        if (wallpaper == null) return;

        ContentValues values = new ContentValues();
        if (wallpaper.getSize() > 0) {
            values.put(KEY_SIZE, wallpaper.getSize());
        }

        if (wallpaper.getMimeType() != null) {
            values.put(KEY_MIME_TYPE, wallpaper.getMimeType());
        }

        if (wallpaper.getDimensions() != null) {
            values.put(KEY_WIDTH, wallpaper.getDimensions().getWidth());
            values.put(KEY_HEIGHT, wallpaper.getDimensions().getHeight());
        }

        if (wallpaper.getColor() != 0) {
            values.put(KEY_COLOR, wallpaper.getColor());
        }

        if (values.size() > 0) {
            mDatabase.get().mSQLiteDatabase.update(TABLE_WALLPAPERS,
                    values, KEY_URL +" = ?", new String[]{wallpaper.getUrl()});
        }
    }

    public void updateWallpapers(@NonNull List<Wallpaper> wallpapers) {
        if (!openDatabase()) {
            LogUtil.e("Database error: updateWallpapers() failed to open database");
            return;
        }

        String query = "UPDATE " +TABLE_WALLPAPERS+ " SET " +KEY_FAVORITE+ " = ?, " +KEY_SIZE+ " = ?, "
                +KEY_MIME_TYPE+ " = ?, " +KEY_WIDTH+ " = ?," +KEY_HEIGHT+ " = ?, " +KEY_COLOR+ " = ? "
                +"WHERE " +KEY_URL+ " = ?";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (Wallpaper wallpaper : wallpapers) {
            statement.clearBindings();

            statement.bindLong(1, wallpaper.isFavorite() ? 1 : 0);
            statement.bindLong(2, wallpaper.getSize());

            String mimeType = wallpaper.getMimeType();
            if (mimeType != null) {
                statement.bindString(3, mimeType);
            } else {
                statement.bindNull(3);
            }

            ImageSize dimension = wallpaper.getDimensions();
            int width = dimension == null ? 0 : dimension.getWidth();
            int height = dimension == null ? 0 : dimension.getHeight();
            statement.bindLong(4, width);
            statement.bindLong(5, height);

            statement.bindLong(6, wallpaper.getColor());
            statement.bindString(7, wallpaper.getUrl());
            statement.execute();
        }

        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void selectCategory(int id, boolean isSelected) {
        if (!openDatabase()) {
            LogUtil.e("Database error: selectCategory() failed to open database");
            return;
        }

        ContentValues values = new ContentValues();
        values.put(KEY_SELECTED, isSelected ? 1 : 0);
        mDatabase.get().mSQLiteDatabase.update(TABLE_CATEGORIES, values, KEY_ID +" = ?", new String[]{String.valueOf(id)});
    }

    public void selectCategoryForMuzei(int id, boolean isSelected) {
        if (!openDatabase()) {
            LogUtil.e("Database error: selectCategoryForMuzei() failed to open database");
            return;
        }

        ContentValues values = new ContentValues();
        values.put(KEY_MUZEI_SELECTED, isSelected ? 1 : 0);
        mDatabase.get().mSQLiteDatabase.update(TABLE_CATEGORIES, values, KEY_ID +" = ?", new String[]{String.valueOf(id)});
    }

    public void favoriteWallpaper(String url, boolean isFavorite) {
        if (!openDatabase()) {
            LogUtil.e("Database error: favoriteWallpaper() failed to open database");
            return;
        }

        ContentValues values = new ContentValues();
        values.put(KEY_FAVORITE, isFavorite ? 1 : 0);
        mDatabase.get().mSQLiteDatabase.update(TABLE_WALLPAPERS, values,
                KEY_URL +" = ?", new String[]{url});
    }

    private List<String> getSelectedCategories(boolean isMuzei) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getSelectedCategories() failed to open database");
            return new ArrayList<>();
        }

        List<String> categories = new ArrayList<>();
        String column = isMuzei ? KEY_MUZEI_SELECTED : KEY_SELECTED;
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_CATEGORIES, new String[]{KEY_NAME}, column +" = ?",
                new String[]{"1"}, null, null, KEY_NAME);
        if (cursor.moveToFirst()) {
            do {
                categories.add(cursor.getString(0));
            } while (cursor.moveToNext());
        }
        cursor.close();
        return categories;
    }

    public List<Category> getCategories() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getCategories() failed to open database");
            return new ArrayList<>();
        }

        List<Category> categories = new ArrayList<>();
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_CATEGORIES,
                null, null, null, null, null, KEY_NAME);
        if (cursor.moveToFirst()) {
            do {
                Category category = Category.Builder()
                        .id(cursor.getInt(cursor.getColumnIndex(KEY_ID)))
                        .name(cursor.getString(cursor.getColumnIndex(KEY_NAME)))
                        .selected(cursor.getInt(cursor.getColumnIndex(KEY_SELECTED)) == 1)
                        .muzeiSelected(cursor.getInt(cursor.getColumnIndex(KEY_MUZEI_SELECTED)) == 1)
                        .build();
                categories.add(category);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return categories;
    }

    public Category getCategoryPreview(@NonNull Category category) {
        String name = category.getName().toLowerCase(Locale.getDefault());
        String query = "SELECT wallpapers.thumbUrl, wallpapers.color, " +
                "(SELECT COUNT(*) FROM wallpapers WHERE LOWER(wallpapers.category) LIKE ?) AS " +KEY_COUNT+
                " FROM wallpapers WHERE LOWER(wallpapers.category) LIKE ? ORDER BY RANDOM() LIMIT 1";
        Cursor cursor = mDatabase.get().mSQLiteDatabase.rawQuery(query, new String[]{"%" +name+ "%", "%" +name+ "%"});
        if (cursor.moveToFirst()) {
            do {
                category.setColor(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)));
                category.setThumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)));
                category.setCount(cursor.getInt(cursor.getColumnIndex(KEY_COUNT)));
            } while (cursor.moveToNext());
        }
        cursor.close();
        return category;
    }

    public List<Category> getWallpaperCategories(String category) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpaperCategories() failed to open database");
            return new ArrayList<>();
        }

        List<Category> categories = new ArrayList<>();
        String[] strings = category.split("[,;]");
        for (String string : strings) {
            String s = string.toLowerCase(Locale.getDefault());
            String query = "SELECT categories.id, categories.name, " +
                    "(SELECT wallpapers.thumbUrl FROM wallpapers WHERE LOWER(wallpapers.category) LIKE ? ORDER BY RANDOM() LIMIT 1) AS thumbUrl, " +
                    "(SELECT COUNT(*) FROM wallpapers WHERE LOWER(wallpapers.category) LIKE ?) AS " +KEY_COUNT+
                    " FROM categories WHERE LOWER(categories.name) = ? LIMIT 1";
            Cursor cursor = mDatabase.get().mSQLiteDatabase.rawQuery(query, new String[]{"%" +s+ "%", "%" +s+ "%", s});
            if (cursor.moveToFirst()) {
                do {
                    Category c = Category.Builder()
                            .id(cursor.getInt(cursor.getColumnIndex(KEY_ID)))
                            .name(cursor.getString(cursor.getColumnIndex(KEY_NAME)))
                            .thumbUrl(cursor.getString(2))
                            .count(cursor.getInt(cursor.getColumnIndex(KEY_COUNT)))
                            .build();
                    categories.add(c);
                } while (cursor.moveToNext());
            }
            cursor.close();
        }
        return categories;
    }

    public int getCategoryCount(String category) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getCategoryCount() failed to open database");
            return 0;
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, "LOWER(" +KEY_CATEGORY+ ") LIKE ?",
                new String[]{"%" +category.toLowerCase(Locale.getDefault())+ "%"}, null, null, null);
        int count = cursor.getCount();
        cursor.close();
        return count;
    }

    @Nullable
    public Wallpaper getWallpaper(String url) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpaper() failed to open database");
            return null;
        }

        Wallpaper wallpaper = null;
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, KEY_URL +" = ?", new String[]{url}, null, null, null, "1");
        if (cursor.moveToFirst()) {
            do {
                int width = cursor.getInt(cursor.getColumnIndex(KEY_WIDTH));
                int height = cursor.getInt(cursor.getColumnIndex(KEY_HEIGHT));
                ImageSize dimensions = null;
                if (width  > 0 && height > 0) {
                    dimensions = new ImageSize(width, height);
                }

                int wId = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ wId;
                }

                wallpaper = Wallpaper.Builder()
                        .id(wId)
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .favorite(cursor.getInt(cursor.getColumnIndex(KEY_FAVORITE)) == 1)
                        .dimensions(dimensions)
                        .mimeType(cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)))
                        .size(cursor.getInt(cursor.getColumnIndex(KEY_SIZE)))
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .build();
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpaper;
    }

    public List<Wallpaper> getFilteredWallpapers(Filter filter) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getFilteredWallpapers() failed to open database");
            return new ArrayList<>();
        }

        List<Wallpaper> wallpapers = new ArrayList<>();

        StringBuilder condition = new StringBuilder();
        List<String> selection = new ArrayList<>();
        for (int i = 0; i < filter.size(); i++) {
            Filter.Options options = filter.get(i);
            if (options != null) {
                if (condition.length() > 0 ) {
                    condition.append(" OR ").append("LOWER(")
                            .append(options.getColumn().getName())
                            .append(")").append(" LIKE ?");
                } else {
                    condition.append("LOWER(")
                            .append(options.getColumn().getName()).append(")")
                            .append(" LIKE ?");
                }
                selection.add("%" +options.getQuery().toLowerCase(Locale.getDefault())+ "%");
            }
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, condition.toString(),
                selection.toArray(new String[selection.size()]),
                null, null, KEY_NAME);
        if (cursor.moveToFirst()) {
            do {
                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                Wallpaper wallpaper = Wallpaper.Builder()
                        .id(id)
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .addedOn(cursor.getString(cursor.getColumnIndex(KEY_ADDED_ON)))
                        .favorite(cursor.getInt(cursor.getColumnIndex(KEY_FAVORITE)) == 1)
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .build();
                wallpapers.add(wallpaper);
            } while (cursor.moveToNext());
        }
        cursor.close();

        Collections.sort(wallpapers, new AlphanumComparator() {

            @Override
            public int compare(Object o1, Object o2) {
                String s1 = ((Wallpaper) o1).getName();
                String s2 = ((Wallpaper) o2).getName();
                return super.compare(s1, s2);
            }
        });
        return wallpapers;
    }

    public List<Wallpaper> getWallpapers() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpapers() failed to open database");
            return new ArrayList<>();
        }

        List<Wallpaper> wallpapers = new ArrayList<>();
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, null, null, null, null, getSortBy(Preferences.get(mContext).getSortBy()));
        if (cursor.moveToFirst()) {
            do {
                int colorIndex = cursor.getColumnIndex(KEY_COLOR);
                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                Wallpaper.Builder builder = Wallpaper.Builder()
                        .id(id)
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .favorite(cursor.getInt(cursor.getColumnIndex(KEY_FAVORITE)) == 1);
                if (colorIndex > -1) {
                    builder.color(cursor.getInt(colorIndex));
                }
                wallpapers.add(builder.build());
            } while (cursor.moveToNext());
        }
        cursor.close();

        if (Preferences.get(mContext).getSortBy() == PopupItem.Type.SORT_NAME) {
            Collections.sort(wallpapers, new AlphanumComparator() {

                @Override
                public int compare(Object o1, Object o2) {
                    String s1 = ((Wallpaper) o1).getName();
                    String s2 = ((Wallpaper) o2).getName();
                    return super.compare(s1, s2);
                }
            });
        }
        return wallpapers;
    }

    public List<Wallpaper> getLatestWallpapers() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getLatestWallpapers() failed to open database");
            return new ArrayList<>();
        }

        List<Wallpaper> wallpapers = new ArrayList<>();
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, null, null, null, null,
                KEY_ADDED_ON+ " DESC, " +KEY_ID,
                String.valueOf(WallpaperBoardApplication.getConfig().getLatestWallpapersDisplayMax()));
        if (cursor.moveToFirst()) {
            do {
                int width = cursor.getInt(cursor.getColumnIndex(KEY_WIDTH));
                int height = cursor.getInt(cursor.getColumnIndex(KEY_HEIGHT));
                ImageSize dimensions = null;
                if (width  > 0 && height > 0) {
                    dimensions = new ImageSize(width, height);
                }

                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                Wallpaper wallpaper = Wallpaper.Builder()
                        .id(id)
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .favorite(cursor.getInt(cursor.getColumnIndex(KEY_FAVORITE)) == 1)
                        .dimensions(dimensions)
                        .mimeType(cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)))
                        .size(cursor.getInt(cursor.getColumnIndex(KEY_SIZE)))
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .build();
                wallpapers.add(wallpaper);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpapers;
    }

    @Nullable
    public Wallpaper getRandomWallpaper() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getRandomWallpaper() failed to open database");
            return null;
        }

        Wallpaper wallpaper = null;
        List<String> selected = getSelectedCategories(true);
        List<String> selection = new ArrayList<>();
        if (selected.size() == 0) return null;

        StringBuilder CONDITION = new StringBuilder();
        for (String item : selected) {
            if (CONDITION.length() > 0 ) {
                CONDITION.append(" OR ").append("LOWER(").append(KEY_CATEGORY).append(")").append(" LIKE ?");
            } else {
                CONDITION.append("LOWER(").append(KEY_CATEGORY).append(")").append(" LIKE ?");
            }
            selection.add("%" +item.toLowerCase(Locale.getDefault())+ "%");
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, CONDITION.toString(),
                selection.toArray(new String[selection.size()]), null, null, "RANDOM()", "1");
        if (cursor.moveToFirst()) {
            do {
                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                wallpaper = Wallpaper.Builder()
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .build();
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpaper;
    }

    public int getWallpapersCount() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpapersCount() failed to open database");
            return 0;
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, null, null, null, null, null, null);
        int rowCount = cursor.getCount();
        cursor.close();
        return rowCount;
    }

    public List<Wallpaper> getFavoriteWallpapers() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getFavoriteWallpapers() failed to open database");
            return new ArrayList<>();
        }

        List<Wallpaper> wallpapers = new ArrayList<>();
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS, null, KEY_FAVORITE +" = ?",
                new String[]{"1"}, null, null, KEY_NAME +", "+ KEY_ID);
        if (cursor.moveToFirst()) {
            do {
                int width = cursor.getInt(cursor.getColumnIndex(KEY_WIDTH));
                int height = cursor.getInt(cursor.getColumnIndex(KEY_HEIGHT));
                ImageSize dimensions = null;
                if (width  > 0 && height > 0) {
                    dimensions = new ImageSize(width, height);
                }

                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                Wallpaper wallpaper = Wallpaper.Builder()
                        .id(id)
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .category(cursor.getString(cursor.getColumnIndex(KEY_CATEGORY)))
                        .favorite(cursor.getInt(cursor.getColumnIndex(KEY_FAVORITE)) == 1)
                        .dimensions(dimensions)
                        .mimeType(cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)))
                        .size(cursor.getInt(cursor.getColumnIndex(KEY_SIZE)))
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .build();
                wallpapers.add(wallpaper);
            } while (cursor.moveToNext());
        }
        cursor.close();

        if (Preferences.get(mContext).getSortBy() == PopupItem.Type.SORT_NAME) {
            Collections.sort(wallpapers, new AlphanumComparator() {

                @Override
                public int compare(Object o1, Object o2) {
                    String s1 = ((Wallpaper) o1).getName();
                    String s2 = ((Wallpaper) o2).getName();
                    return super.compare(s1, s2);
                }
            });
        }
        return wallpapers;
    }

    public void deleteWallpapers(@NonNull List<Wallpaper> wallpapers) {
        if (!openDatabase()) {
            LogUtil.e("Database error: deleteWallpapers() failed to open database");
            return;
        }

        String query = "DELETE FROM " +TABLE_WALLPAPERS+ " WHERE " +KEY_URL+ " = ?";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (Wallpaper wallpaper : wallpapers) {
            statement.clearBindings();
            statement.bindString(1, wallpaper.getUrl());
            statement.execute();
        }

        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void resetAutoIncrement() {
        if (!openDatabase()) {
            LogUtil.e("Database error: resetAutoIncrement() failed to open database");
            return;
        }

        mSQLiteDatabase.delete("SQLITE_SEQUENCE", "NAME = ?", new String[]{TABLE_WALLPAPERS});
    }

    public void deleteCategories(@NonNull List<Category> categories) {
        if (!openDatabase()) {
            LogUtil.e("Database error: deleteCategories() failed to open database");
            return;
        }

        String query = "DELETE FROM " +TABLE_CATEGORIES+ " WHERE " +KEY_NAME+ " = ?";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (Category category : categories) {
            statement.clearBindings();
            statement.bindString(1, category.getName());
            statement.execute();
        }

        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    private String getSortBy(PopupItem.Type type) {
        switch (type) {
            case SORT_LATEST:
                return KEY_ADDED_ON +" DESC, "+ KEY_ID;
            case SORT_OLDEST:
                return KEY_ADDED_ON +", "+ KEY_ID +" DESC";
            case SORT_NAME:
                return KEY_NAME;
            case SORT_RANDOM:
                return "RANDOM()";
            default:
                return KEY_ADDED_ON +" DESC, "+ KEY_ID;
        }
    }
}
 public class LocaleHelper {

    public static void setLocale(@NonNull Context context) {
        Locale locale = Preferences.get(context).getCurrentLocale();
        Locale.setDefault(locale);

        Configuration configuration = context.getResources().getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            LocaleList.setDefault(new LocaleList(locale));
            configuration.setLocales(new LocaleList(locale));
            configuration.setLocale(locale);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(locale);
        } else {
            configuration.locale = locale;
        }

        //Todo:
        // Find out a solution to use context.createConfigurationContext(configuration);
        // It breaks onConfigurationChanged()
        // Still can't find a way to fix that
        // No other options, better use deprecated code for now
        context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics());
    }

    public static Locale getSystem() {
        Locale locale = Resources.getSystem().getConfiguration().locale;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            locale = Resources.getSystem().getConfiguration().getLocales().get(0);
        }
        return locale;
    }

    public static List<Language> getAvailableLanguages(@NonNull Context context) {
        List<Language> languages = new ArrayList<>();
        String[] names = context.getResources().getStringArray(R.array.languages_name);
        String[] codes = context.getResources().getStringArray(R.array.languages_code);

        for (int i = 0; i < names.length; i++) {
            Language language = new Language(names[i], getLocale(codes[i]));
            languages.add(language);
        }
        return languages;
    }

    public static Language getCurrentLanguage(@NonNull Context context) {
        List<Language> languages = getAvailableLanguages(context);
        Locale locale = Preferences.get(context).getCurrentLocale();

        for (Language language : languages) {
            Locale l = language.getLocale();
            if (locale.toString().equals(l.toString())) {
                return language;
            }
        }
        return new Language("English", new Locale("en", "US"));
    }

    public static Locale getLocale(String language) {
        String[] codes = language.split("_");
        if (codes.length == 2) {
            return new Locale(codes[0], codes[1]);
        }
        return Locale.getDefault();
    }
}
 public class TapIntroHelper {

    public static void showWallpaperPreviewIntro(@NonNull Context context, @ColorInt int color) {
        if (Preferences.get(context).isTimeToShowWallpaperPreviewIntro()) {
            AppCompatActivity activity = (AppCompatActivity) context;

            RelativeLayout rootView = activity.findViewById(R.id.bottom_panel);
            if (rootView == null) return;

            new Handler().postDelayed(() -> {
                try {
                    int baseColor = color;
                    if (baseColor == 0) {
                        baseColor = ColorHelper.getAttributeColor(context, R.attr.colorAccent);
                    }

                    int primary = ColorHelper.getTitleTextColor(baseColor);
                    int secondary = ColorHelper.setColorAlpha(primary, 0.7f);

                    TapTargetSequence tapTargetSequence = new TapTargetSequence(activity);
                    tapTargetSequence.continueOnCancel(true);

                    Typeface title = TypefaceHelper.getMedium(context);
                    //Todo:
                    //Typeface description = TypefaceHelper.getRegular(context);

                    ImageView apply = rootView.findViewById(R.id.menu_apply);
                    ImageView save = rootView.findViewById(R.id.menu_save);
                    ImageView preview = rootView.findViewById(R.id.menu_preview);

                    TapTarget tapTarget = TapTarget.forView(apply,
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_apply),
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_apply_desc))
                            .titleTextColorInt(primary)
                            .descriptionTextColorInt(secondary)
                            .targetCircleColorInt(primary)
                            .outerCircleColorInt(baseColor)
                            .drawShadow(true);

                    TapTarget tapTarget1 = TapTarget.forView(save,
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_save),
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_save_desc))
                            .titleTextColorInt(primary)
                            .descriptionTextColorInt(secondary)
                            .targetCircleColorInt(primary)
                            .outerCircleColorInt(baseColor)
                            .drawShadow(true);

                    TapTarget tapTarget2 = TapTarget.forView(preview,
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_full),
                            context.getResources().getString(R.string.tap_intro_wallpaper_preview_full_desc))
                            .titleTextColorInt(primary)
                            .descriptionTextColorInt(secondary)
                            .targetCircleColorInt(primary)
                            .outerCircleColorInt(baseColor)
                            .drawShadow(true);

                    if (title != null) {
                        //Todo:
                        //tapTarget.titleTypeface(title);
                        //tapTarget1.titleTypeface(title);
                        //tapTarget2.titleTypeface(title);
                        tapTarget.textTypeface(title);
                        tapTarget1.textTypeface(title);
                        tapTarget2.textTypeface(title);
                    }

                    //if (description != null) {
                        //Todo:
                        //tapTarget.descriptionTypeface(description);
                        //tapTarget1.descriptionTypeface(description);
                        //tapTarget2.descriptionTypeface(description);
                    //}

                    tapTargetSequence.target(tapTarget);
                    if (context.getResources().getBoolean(R.bool.enable_wallpaper_download)) {
                        tapTargetSequence.target(tapTarget1);
                    }
                    tapTargetSequence.target(tapTarget2);

                    tapTargetSequence.listener(new TapTargetSequence.Listener() {
                        @Override
                        public void onSequenceFinish() {
                            Preferences.get(context).setTimeToShowWallpaperPreviewIntro(false);

                            SlidingUpPanelLayout panelLayout = activity.findViewById(R.id.sliding_layout);
                            if (panelLayout != null) {
                                new Handler().postDelayed(() -> panelLayout.setPanelState(
                                        SlidingUpPanelLayout.PanelState.EXPANDED), 300);
                            }
                        }

                        @Override
                        public void onSequenceStep(TapTarget tapTarget, boolean b) {

                        }

                        @Override
                        public void onSequenceCanceled(TapTarget tapTarget) {

                        }
                    });
                    tapTargetSequence.start();
                } catch (Exception e) {
                    LogUtil.e(Log.getStackTraceString(e));
                }
            }, 100);
        }
    }
}
 public class Category {

    private int mId;
    private String mName;
    private String mThumbUrl;
    private boolean mIsSelected;
    private boolean mIsMuzeiSelected;
    private int mCount;
    private int mColor;

    private Category(String name) {
        mName = name;
    }

    public int getId() {
        return mId;
    }

    public String getName() {
        return mName;
    }

    public String getThumbUrl() {
        return mThumbUrl;
    }

    public boolean isSelected() {
        return mIsSelected;
    }

    public boolean isMuzeiSelected() {
        return mIsMuzeiSelected;
    }

    public int getCount() {
        return mCount;
    }

    public int getColor() {
        return mColor;
    }

    public String getCategoryCount() {
        if (mCount > 100 && mCount < 1000) {
            return "99+";
        } else if (mCount > 1000 && mCount < 10000) {
            String string = String.valueOf(mCount);
            int lastIndex = string.length() - 3;
            if (lastIndex >= 0 && lastIndex < string.length()) {
                return string.substring(0, lastIndex) + "K+";
            }
        } else if (mCount > 10000) {
            return "9K+";
        }
        return String.valueOf(mCount);
    }

    public void setId(int id) {
        mId = id;
    }

    public void setThumbUrl(String thumbUrl) {
        mThumbUrl = thumbUrl;
    }

    public void setSelected(boolean isSelected) {
        mIsSelected = isSelected;
    }

    public void setMuzeiSelected(boolean isMuzeiSelected) {
        mIsMuzeiSelected = isMuzeiSelected;
    }

    public void setCount(int count) {
        mCount = count;
    }

    public void setColor(int color) {
        mColor = color;
    }

    @Override
    public boolean equals(Object object) {
        boolean equals = false;
        if (object != null && object instanceof Category) {
            equals = mName.equals(((Category) object).getName());
        }
        return equals;
    }

    public static Builder Builder() {
        return new Builder();
    }

    public static class Builder {

        private int mId;
        private String mName;
        private String mThumbUrl;
        private boolean mIsSelected;
        private boolean mIsMuzeiSelected;
        private int mCount;
        private int mColor;

        private Builder() {
            mId = -1;
            mCount = 0;
            mIsMuzeiSelected = false;
            mIsSelected = false;
        }

        public Builder id(int id) {
            mId = id;
            return this;
        }

        public Builder name(String name) {
            mName = name;
            return this;
        }

        public Builder thumbUrl(String thumbUrl) {
            mThumbUrl = thumbUrl;
            return this;
        }

        public Builder selected(boolean isSelected) {
            mIsSelected = isSelected;
            return this;
        }

        public Builder muzeiSelected(boolean isMuzeiSelected) {
            mIsMuzeiSelected = isMuzeiSelected;
            return this;
        }

        public Builder count(int count) {
            mCount = count;
            return this;
        }

        public Builder color(int color) {
            mColor = color;
            return this;
        }

        public Category build() {
            Category category = new Category(mName);
            category.setId(mId);
            category.setThumbUrl(mThumbUrl);
            category.setSelected(mIsSelected);
            category.setMuzeiSelected(mIsMuzeiSelected);
            category.setCount(mCount);
            category.setColor(mColor);
            return category;
        }
    }
}
 public class ColorPalette {

    private List<Integer> mColors;

    public ColorPalette() {
        mColors = new ArrayList<>();
    }

    public ColorPalette add(@ColorInt int color) {
        if (color == 0) {
            LogUtil.e("color: " +color+ " isn't valid, color ignored");
            return this;
        }
        if (!mColors.contains(color)) {
            mColors.add(color);
            return this;
        }
        LogUtil.e("ColorPalette: color already added");
        return this;
    }

    @ColorInt
    public int get(int index) {
        if (index >= 0 && index < mColors.size()) {
            return mColors.get(index);
        }
        LogUtil.e("ColorPalette: index out of bounds");
        return -1;
    }

    @Nullable
    public String getHex(int index) {
        if (index >= 0 && index < mColors.size()) {
            return String.format("#%06X", (0xFFFFFF & get(index)));
        }
        LogUtil.e("ColorPalette: index out of bounds");
        return null;
    }

    public int size() {
        return mColors.size();
    }
}
 public class PopupItem {

    private final String mTitle;
    private int mIcon;
    private boolean mShowCheckbox;
    private boolean mCheckboxValue;
    private boolean mIsSelected;
    private Type mType;

    public PopupItem(String title) {
        mTitle = title;
        mShowCheckbox = false;
        mCheckboxValue = false;
        mIsSelected = false;
    }

    public PopupItem setIcon(@DrawableRes int icon) {
        mIcon = icon;
        return this;
    }

    public PopupItem setShowCheckbox(boolean showCheckbox) {
        mShowCheckbox = showCheckbox;
        return this;
    }

    public PopupItem setCheckboxValue(boolean checkboxValue) {
        mCheckboxValue = checkboxValue;
        return this;
    }

    public PopupItem setSelected(boolean selected) {
        mIsSelected = selected;
        return this;
    }

    public PopupItem setType(Type type) {
        mType = type;
        return this;
    }

    public String getTitle() {
        return mTitle;
    }

    @DrawableRes
    public int getIcon() {
        return mIcon;
    }

    public boolean isShowCheckbox() {
        return mShowCheckbox;
    }

    public boolean getCheckboxValue() {
        return mCheckboxValue;
    }

    public boolean isSelected() {
        return mIsSelected;
    }

    public Type getType() {
        return mType;
    }

    public enum Type {
        WALLPAPER_CROP,
        HOMESCREEN,
        LOCKSCREEN,
        HOMESCREEN_LOCKSCREEN,
        DOWNLOAD,
        SORT_LATEST,
        SORT_OLDEST,
        SORT_NAME,
        SORT_RANDOM,
    }

    public static List<PopupItem> getApplyItems(@NonNull Context context) {
        List<PopupItem> items = new ArrayList<>();

        //Todo: wait until google fix the issue, then enable wallpaper crop again on API 26+
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            items.add(new PopupItem(context.getResources().getString(R.string.menu_wallpaper_crop))
                    .setType(Type.WALLPAPER_CROP)
                    .setCheckboxValue(Preferences.get(context).isCropWallpaper())
                    .setShowCheckbox(true));
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            items.add(new PopupItem(context.getResources().getString(R.string.menu_apply_lockscreen))
                    .setType(Type.LOCKSCREEN)
                    .setIcon(R.drawable.ic_toolbar_lockscreen));
        }

        items.add(new PopupItem(context.getResources().getString(R.string.menu_apply_homescreen))
                .setType(Type.HOMESCREEN)
                .setIcon(R.drawable.ic_toolbar_homescreen));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            items.add(new PopupItem(context.getResources().getString(R.string.menu_apply_homescreen_lockscreen))
                    .setType(Type.HOMESCREEN_LOCKSCREEN)
                    .setIcon(R.drawable.ic_toolbar_homescreen_lockscreen));
        }

        if (context.getResources().getBoolean(R.bool.enable_wallpaper_download)) {
            items.add(new PopupItem(context.getResources().getString(R.string.menu_save))
                    .setType(Type.DOWNLOAD)
                    .setIcon(R.drawable.ic_toolbar_download));
        }
        return items;
    }

    public static List<PopupItem> getSortItems(@NonNull Context context, boolean selection) {
        List<PopupItem> items = new ArrayList<>();
        items.add(new PopupItem(context.getResources().getString(R.string.menu_sort_latest))
                .setType(Type.SORT_LATEST)
                .setIcon(R.drawable.ic_toolbar_sort_latest));

        items.add(new PopupItem(context.getResources().getString(R.string.menu_sort_oldest))
                .setType(Type.SORT_OLDEST)
                .setIcon(R.drawable.ic_toolbar_sort_oldest));

        items.add(new PopupItem(context.getResources().getString(R.string.menu_sort_name))
                .setType(Type.SORT_NAME)
                .setIcon(R.drawable.ic_toolbar_sort_name));

        items.add(new PopupItem(context.getResources().getString(R.string.menu_sort_random))
                .setType(Type.SORT_RANDOM)
                .setIcon(R.drawable.ic_toolbar_sort_random));

        if (selection) {
            Type type = Preferences.get(context).getSortBy();
            int order = Preferences.get(context).getSortByOrder(type);
            if (order >= 0 && order < items.size()) {{
                items.get(order).setSelected(true);
            }}
        }
        return items;
    }
}
 public class Wallpaper {

    private int mId;
    private final String mName;
    private final String mAuthor;
    private final String mThumbUrl;
    private final String mUrl;
    private final String mCategory;
    private final String mAddedOn;
    private int mColor;
    private String mMimeType;
    private int mSize;
    private boolean mIsFavorite;
    private ImageSize mDimensions;

    private Wallpaper(String name, String author, String url, String thumbUrl, String category, String addedOn) {
        mName = name;
        mAuthor = author;
        mUrl = url;
        mThumbUrl = thumbUrl;
        mCategory = category;
        mAddedOn = addedOn;
    }

    public int getId() {
        return mId;
    }

    public String getName() {
        return mName;
    }

    public String getAuthor() {
        return mAuthor;
    }

    public String getUrl() {
        return mUrl;
    }

    public String getThumbUrl() {
        return mThumbUrl;
    }

    public String getCategory() {
        return mCategory;
    }

    public String getAddedOn() {
        return mAddedOn;
    }

    public int getColor() {
        return mColor;
    }

    public String getMimeType() {
        return mMimeType;
    }

    public int getSize() {
        return mSize;
    }

    public ImageSize getDimensions() {
        return mDimensions;
    }

    public boolean isFavorite() {
        return mIsFavorite;
    }

    public void setId(int id) {
        mId = id;
    }

    public void setColor(int color) {
        mColor = color;
    }

    public void setMimeType(String mimeType) {
        mMimeType = mimeType;
    }

    public void setSize(int size) {
        mSize = size;
    }

    public void setDimensions(ImageSize dimensions) {
        mDimensions = dimensions;
    }

    public void setFavorite(boolean isFavorite) {
        mIsFavorite = isFavorite;
    }

    @Override
    public boolean equals(Object object) {
        boolean equals = false;
        if (object != null && object instanceof Wallpaper) {
            equals = mAuthor.equals(((Wallpaper) object).getAuthor()) &&
                    mUrl.equals(((Wallpaper) object).getUrl()) &&
                    mThumbUrl.equals(((Wallpaper) object).getThumbUrl()) &&
                    mCategory.equals(((Wallpaper) object).getCategory());
        }
        return equals;
    }

    public static Builder Builder() {
        return new Builder();
    }

    public static class Builder {

        private int mId;
        private String mName;
        private String mAuthor;
        private String mThumbUrl;
        private String mUrl;
        private String mCategory;
        private String mAddedOn;
        private int mColor;
        private String mMimeType;
        private int mSize;
        private boolean mIsFavorite;
        private ImageSize mDimensions;

        private Builder() {
            mId = -1;
            mSize = 0;
            mColor = 0;
        }

        public Builder id(int id) {
            mId = id;
            return this;
        }

        public Builder name(String name) {
            mName = name;
            return this;
        }

        public Builder author(String author) {
            mAuthor = author;
            return this;
        }

        public Builder url(String url) {
            mUrl = url;
            return this;
        }

        public Builder thumbUrl(String thumbUrl) {
            mThumbUrl = thumbUrl;
            return this;
        }

        public Builder category(String category) {
            mCategory = category;
            return this;
        }

        public Builder addedOn(String addedOn) {
            mAddedOn = addedOn;
            return this;
        }

        public Builder favorite(boolean isFavorite) {
            mIsFavorite = isFavorite;
            return this;
        }

        public Builder dimensions(ImageSize dimensions) {
            mDimensions = dimensions;
            return this;
        }

        public Builder mimeType(String mimeType) {
            mMimeType = mimeType;
            return this;
        }

        public Builder size(int size) {
            mSize = size;
            return this;
        }

        public Builder color(int color) {
            mColor = color;
            return this;
        }

        public Wallpaper build() {
            Wallpaper wallpaper = new Wallpaper(mName, mAuthor, mUrl, mThumbUrl, mCategory, mAddedOn);
            wallpaper.setId(mId);
            wallpaper.setDimensions(mDimensions);
            wallpaper.setFavorite(mIsFavorite);
            wallpaper.setMimeType(mMimeType);
            wallpaper.setSize(mSize);
            wallpaper.setColor(mColor);
            return wallpaper;
        }
    }
}
 public class Preferences {

    private static final String PREFERENCES_NAME = "wallpaper_board_preferences";

    private static final String KEY_LICENSED = "licensed";
    private static final String KEY_FIRST_RUN = "first_run";
    private static final String KEY_DARK_THEME = "dark_theme";
    private static final String KEY_ROTATE_TIME = "rotate_time";
    private static final String KEY_ROTATE_MINUTE = "rotate_minute";
    private static final String KEY_WIFI_ONLY = "wifi_only";
    private static final String KEY_WALLS_DIRECTORY = "wallpaper_download_directory";
    private static final String KEY_CROP_WALLPAPER = "crop_wallpaper";
    private static final String KEY_WALLPAPER_PREVIEW_INTRO = "wallpaper_preview_intro";
    private static final String KEY_CURRENT_LOCALE = "current_locale";
    private static final String KEY_LOCALE_DEFAULT = "localeDefault";
    private static final String KEY_WALLPAPER_TOOLTIP = "wallpaper_tooltip";
    private static final String KEY_SORT_BY = "sort_by";
    private static final String KEY_HIGH_QUALITY_PREVIEW = "high_quality_preview";
    private static final String KEY_BACKUP = "backup";
    private static final String KEY_PREVIOUS_BACKUP = "previousBackup";

    private static WeakReference<Preferences> mPreferences;
    private final Context mContext;

    private Preferences(@NonNull Context context) {
        mContext = context;
    }

    @NonNull
    public static Preferences get(@NonNull Context context) {
        if (mPreferences == null || mPreferences.get() == null) {
            mPreferences = new WeakReference<>(new Preferences(context));
        }
        return mPreferences.get();
    }

    private SharedPreferences getSharedPreferences() {
        return mPreferences.get().mContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
    }

    public void clearPreferences() {
        boolean isLicensed = isLicensed();
        getSharedPreferences().edit().clear().apply();

        if (isLicensed) {
            setFirstRun(false);
            setLicensed(true);
        }
    }

    public boolean isLicensed() {
        return getSharedPreferences().getBoolean(KEY_LICENSED, false);
    }

    public void setLicensed(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_LICENSED, bool).apply();
    }

    public boolean isFirstRun() {
        return getSharedPreferences().getBoolean(KEY_FIRST_RUN, true);
    }

    public void setFirstRun(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_FIRST_RUN, bool).apply();
    }

    public boolean isDarkTheme() {
        boolean useDarkTheme = mPreferences.get().mContext.getResources().getBoolean(R.bool.use_dark_theme);
        boolean isThemingEnabled = WallpaperBoardApplication.getConfig().isDashboardThemingEnabled();
        if (!isThemingEnabled) return useDarkTheme;
        return getSharedPreferences().getBoolean(KEY_DARK_THEME, useDarkTheme);
    }

    public void setDarkTheme(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_DARK_THEME, bool).apply();
    }

    public boolean isShadowEnabled() {
        return WallpaperBoardApplication.getConfig().isShadowEnabled();
    }

    public boolean isTimeToShowWallpaperPreviewIntro() {
        return getSharedPreferences().getBoolean(KEY_WALLPAPER_PREVIEW_INTRO, true);
    }

    public void setTimeToShowWallpaperPreviewIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WALLPAPER_PREVIEW_INTRO, bool).apply();
    }

    public void setRotateTime (int time) {
        getSharedPreferences().edit().putInt(KEY_ROTATE_TIME, time).apply();
    }

    public int getRotateTime() {
        return getSharedPreferences().getInt(KEY_ROTATE_TIME, 3600000);
    }

    public void setRotateMinute (boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_ROTATE_MINUTE, bool).apply();
    }

    public boolean isRotateMinute() {
        return getSharedPreferences().getBoolean(KEY_ROTATE_MINUTE, false);
    }

    public boolean isWifiOnly() {
        return getSharedPreferences().getBoolean(KEY_WIFI_ONLY, false);
    }

    public void setWifiOnly (boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WIFI_ONLY, bool).apply();
    }

    void setWallsDirectory(String directory) {
        getSharedPreferences().edit().putString(KEY_WALLS_DIRECTORY, directory).apply();
    }

    public String getWallsDirectory() {
        return getSharedPreferences().getString(KEY_WALLS_DIRECTORY, "");
    }

    public boolean isCropWallpaper() {
        return getSharedPreferences().getBoolean(KEY_CROP_WALLPAPER,
                WallpaperBoardApplication.getConfig().isCropWallpaperEnabledByDefault());
    }

    public void setCropWallpaper(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_CROP_WALLPAPER, bool).apply();
    }

    public boolean isShowWallpaperTooltip() {
        return getSharedPreferences().getBoolean(KEY_WALLPAPER_TOOLTIP, true);
    }

    public void setShowWallpaperTooltip(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WALLPAPER_TOOLTIP, bool).apply();
    }

    public boolean isHighQualityPreviewEnabled() {
        return getSharedPreferences().getBoolean(KEY_HIGH_QUALITY_PREVIEW,
                WallpaperBoardApplication.getConfig().isHighQualityPreviewEnabled());
    }

    public void setHighQualityPreviewEnabled(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_HIGH_QUALITY_PREVIEW, bool).apply();
    }

    public boolean isBackupRestored() {
        return getSharedPreferences().getBoolean(KEY_BACKUP, false);
    }

    public void setBackupRestored(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_BACKUP, bool).apply();
    }

    public boolean isPreviousBackupExist() {
        return getSharedPreferences().getBoolean(KEY_PREVIOUS_BACKUP, false);
    }

    public void setPreviousBackupExist(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_PREVIOUS_BACKUP, bool).apply();
    }

    public Locale getCurrentLocale() {
        if (isLocaleDefault()) {
            Locale defaultLocale = getDefaultLocale();
            if (defaultLocale != null) {
                return defaultLocale;
            }
        }

        String code = getSharedPreferences().getString(KEY_CURRENT_LOCALE, "en_US");
        return LocaleHelper.getLocale(code);
    }

    public void setCurrentLocale(String code) {
        getSharedPreferences().edit().putString(KEY_CURRENT_LOCALE, code).apply();
    }

    public boolean isLocaleDefault() {
        return getSharedPreferences().getBoolean(KEY_LOCALE_DEFAULT, true);
    }

    public void setLocaleDefault(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_LOCALE_DEFAULT, bool).apply();
    }

    @Nullable
    private Locale getDefaultLocale() {
        Locale locale = LocaleHelper.getSystem();
        List<Language> languages = LocaleHelper.getAvailableLanguages(mContext);

        Locale currentLocale = null;
        for (Language language : languages) {
            Locale l = language.getLocale();
            if (locale.toString().equals(l.toString())) {
                currentLocale = l;
                break;
            }
        }

        if (currentLocale == null) {
            for (Language language : languages) {
                Locale l = language.getLocale();
                if (locale.getLanguage().equals(l.getLanguage())) {
                    currentLocale = l;
                    break;
                }
            }
        }
        return currentLocale;
    }

    public void setSortBy(PopupItem.Type type) {
        getSharedPreferences().edit().putInt(KEY_SORT_BY, getSortByOrder(type)).apply();
    }

    public int getSortByOrder(PopupItem.Type type) {
        switch (type) {
            case SORT_LATEST:
                return 0;
            case SORT_OLDEST:
                return 1;
            case SORT_NAME:
                return 2;
            case SORT_RANDOM:
                return 3;
            default:
                return 2;
        }
    }

    public PopupItem.Type getSortBy(){
        int sort = getSharedPreferences().getInt(KEY_SORT_BY, 2);
        if (sort == 0) {
            return PopupItem.Type.SORT_LATEST;
        } else if (sort == 1) {
            return PopupItem.Type.SORT_OLDEST;
        } else if (sort == 2) {
            return PopupItem.Type.SORT_NAME;
        } else if (sort == 3) {
            return PopupItem.Type.SORT_RANDOM;
        }
        return PopupItem.Type.SORT_NAME;
    }

    public boolean isConnectedToNetwork() {
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    mPreferences.get().mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        } catch (Exception e) {
            return false;
        }
    }

    public boolean isConnectedAsPreferred() {
        try {
            if (isWifiOnly()) {
                ConnectivityManager connectivityManager = (ConnectivityManager)
                        mPreferences.get().mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                return activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
                        activeNetworkInfo.isConnected();
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
 public class LocalFavoritesRestoreTask extends AsyncTask<Void, Void, Boolean> {

    private boolean mIsBackupExist;
    private boolean mIsStorageGranted;
    private WeakReference<Context> mContext;

    private LocalFavoritesRestoreTask(Context context) {
        mContext = new WeakReference<>(context);
        mIsStorageGranted = PermissionHelper.isStorageGranted(mContext.get());
    }

    public AsyncTask start() {
        return start(SERIAL_EXECUTOR);
    }

    public AsyncTask start(@NonNull Executor executor) {
        return executeOnExecutor(executor);
    }

    public static LocalFavoritesRestoreTask with(@NonNull Context context) {
        return new LocalFavoritesRestoreTask(context);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        File file = new File(BackupHelper.getDefaultDirectory(mContext.get()), BackupHelper.FILE_BACKUP);
        mIsBackupExist = file.exists();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        while (!isCancelled()) {
            try {
                Thread.sleep(1);
                if (!mIsStorageGranted) {
                    LogUtil.e("Storage permission not granted, it's required to restore local backup");
                    return false;
                }

                if (mIsBackupExist) {
                    File file = new File(BackupHelper.getDefaultDirectory(mContext.get()), BackupHelper.FILE_BACKUP);
                    XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
                    xmlPullParserFactory.setNamespaceAware(true);
                    XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser();
                    xmlPullParser.setInput(new InputStreamReader(new FileInputStream(file)));

                    while (xmlPullParser.getEventType() != XmlPullParser.END_DOCUMENT) {
                        if (xmlPullParser.getEventType() == XmlPullParser.START_TAG) {
                            if (xmlPullParser.getName().equals(Extras.EXTRA_ITEM)) {
                                String url = xmlPullParser.getAttributeValue(null, Extras.EXTRA_URL);
                                Database.get(mContext.get()).favoriteWallpaper(
                                        URLDecoder.decode(url, "utf-8"), true);
                            }
                        }
                        xmlPullParser.next();
                    }
                    Preferences.get(mContext.get()).setBackupRestored(true);
                    Preferences.get(mContext.get()).setPreviousBackupExist(false);
                    return true;
                }

                LogUtil.d("Backup file not found");
                Preferences.get(mContext.get()).setBackupRestored(true);
                Preferences.get(mContext.get()).setPreviousBackupExist(false);
                return false;
            } catch (Exception e) {
                LogUtil.e(Log.getStackTraceString(e));
                return false;
            }
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (mContext.get() == null) return;
        if (mContext.get() instanceof Activity) {
            if (((Activity) mContext.get()).isFinishing()) return;
        }

        if (aBoolean) {
            Toast.makeText(mContext.get(), R.string.wallpapers_favorite_restored, Toast.LENGTH_LONG).show();
        }
    }
}
 public class WallpaperApplyTask extends AsyncTask<Void, Void, Boolean> implements WallpaperPropertiesLoaderTask.Callback{

    private final WeakReference<Context> mContext;
    private Apply mApply;
    private RectF mRectF;
    private Executor mExecutor;
    private Wallpaper mWallpaper;
    private MaterialDialog mDialog;

    private WallpaperApplyTask(Context context) {
        mContext = new WeakReference<>(context);
    }

    public WallpaperApplyTask to(Apply apply) {
        mApply = apply;
        return this;
    }

    public WallpaperApplyTask wallpaper(@NonNull Wallpaper wallpaper) {
        mWallpaper = wallpaper;
        return this;
    }

    public WallpaperApplyTask crop(@Nullable RectF rectF) {
        mRectF = rectF;
        return this;
    }

    public AsyncTask start() {
        return start(SERIAL_EXECUTOR);
    }

    public AsyncTask start(@NonNull Executor executor) {
        if (mDialog == null) {
            int color = mWallpaper.getColor();
            if (color == 0) {
                color = ColorHelper.getAttributeColor(mContext.get(), R.attr.colorAccent);
            }

            final MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext.get());
            builder.widgetColor(color)
                    .typeface(TypefaceHelper.getMedium(mContext.get()), TypefaceHelper.getRegular(mContext.get()))
                    .progress(true, 0)
                    .cancelable(false)
                    .progressIndeterminateStyle(true)
                    .content(R.string.wallpaper_loading)
                    .positiveColor(color)
                    .positiveText(android.R.string.cancel)
                    .onPositive((dialog, which) -> {
                        ImageLoader.getInstance().stop();
                        cancel(true);
                    });

            mDialog = builder.build();
        }

        if (!mDialog.isShowing()) mDialog.show();

        mExecutor = executor;
        if (mWallpaper == null) {
            LogUtil.e("WallpaperApply cancelled, wallpaper is null");
            return null;
        }

        if (mWallpaper.getDimensions() == null) {
            return WallpaperPropertiesLoaderTask.prepare(mContext.get())
                    .wallpaper(mWallpaper)
                    .callback(this)
                    .start(AsyncTask.THREAD_POOL_EXECUTOR);
        }
        return executeOnExecutor(executor);
    }

    public static WallpaperApplyTask prepare(@NonNull Context context) {
        return new WallpaperApplyTask(context);
    }

    @Override
    public void onPropertiesReceived(Wallpaper wallpaper) {
        mWallpaper = wallpaper;
        if (mExecutor == null) mExecutor = SERIAL_EXECUTOR;
        if (mWallpaper.getDimensions() == null) {
            LogUtil.e("WallpaperApply cancelled, unable to retrieve wallpaper dimensions");

            if (mContext.get() == null) return;
            if (mContext.get() instanceof Activity) {
                if (((Activity) mContext.get()).isFinishing())
                    return;
            }

            if (mDialog != null && mDialog.isShowing()) {
                mDialog.dismiss();
            }

            Toast.makeText(mContext.get(), R.string.wallpaper_apply_failed,
                    Toast.LENGTH_LONG).show();
            return;
        }

        try {
            executeOnExecutor(mExecutor);
        } catch (IllegalStateException e) {
            LogUtil.e(Log.getStackTraceString(e));
        }
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        while (!isCancelled()) {
            try {
                Thread.sleep(1);
                ImageSize imageSize = WallpaperHelper.getTargetSize(mContext.get());

                LogUtil.d("original rectF: " +mRectF);

                if (mRectF != null && Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
                    Point point = WindowHelper.getScreenSize(mContext.get());
                    int height = point.y - WindowHelper.getStatusBarHeight(mContext.get()) - WindowHelper.getNavigationBarHeight(mContext.get());
                    float heightFactor = (float) imageSize.getHeight() / (float) height;
                    mRectF = WallpaperHelper.getScaledRectF(mRectF, heightFactor, 1f);
                }

                if (mRectF == null && Preferences.get(mContext.get()).isCropWallpaper()) {
                    /*
                     * Create a center crop rectF if wallpaper applied from grid, not opening the preview first
                     */
                    float widthScaleFactor = (float) imageSize.getHeight() / (float) mWallpaper.getDimensions().getHeight();

                    float side = ((float) mWallpaper.getDimensions().getWidth() * widthScaleFactor - (float) imageSize.getWidth())/2f;
                    float leftRectF = 0f - side;
                    float rightRectF = (float) mWallpaper.getDimensions().getWidth() * widthScaleFactor - side;
                    float topRectF = 0f;
                    float bottomRectF = (float) imageSize.getHeight();
                    mRectF = new RectF(leftRectF, topRectF, rightRectF, bottomRectF);
                    LogUtil.d("created center crop rectF: " +mRectF);
                }

                ImageSize adjustedSize = imageSize;
                RectF adjustedRectF = mRectF;

                float scaleFactor = (float) mWallpaper.getDimensions().getHeight() / (float) imageSize.getHeight();
                if (scaleFactor > 1f) {
                    /*
                     * Applying original wallpaper size caused a problem (wallpaper zoomed in)
                     * if wallpaper dimension bigger than device screen resolution
                     *
                     * Solution: Resize wallpaper to match screen resolution
                     */

                    /*
                     * Use original wallpaper size:
                     * adjustedSize = new ImageSize(width, height);
                     */

                    /*
                     * Adjust wallpaper size to match screen resolution:
                     */
                    float widthScaleFactor = (float) imageSize.getHeight() / (float) mWallpaper.getDimensions().getHeight();
                    int adjustedWidth = Float.valueOf((float) mWallpaper.getDimensions().getWidth() * widthScaleFactor).intValue();
                    adjustedSize = new ImageSize(adjustedWidth, imageSize.getHeight());

                    if (adjustedRectF != null) {
                        /*
                         * If wallpaper crop enabled, original wallpaper size should be loaded first
                         */
                        adjustedSize = new ImageSize(mWallpaper.getDimensions().getWidth(), mWallpaper.getDimensions().getHeight());
                        adjustedRectF = WallpaperHelper.getScaledRectF(mRectF, scaleFactor, scaleFactor);
                        LogUtil.d("adjusted rectF: " + adjustedRectF);
                    }

                    LogUtil.d(String.format(Locale.getDefault(), "adjusted bitmap: %d x %d",
                            adjustedSize.getWidth(), adjustedSize.getHeight()));
                }

                int call = 1;
                do {
                    /*
                     * Load the bitmap first
                     */
                    Bitmap loadedBitmap = ImageLoader.getInstance().loadImageSync(
                            mWallpaper.getUrl(), adjustedSize, ImageConfig.getWallpaperOptions());
                    if (loadedBitmap != null) {
                        try {
                            /*
                             * Checking if loaded bitmap resolution supported by the device
                             * If texture size too big then resize it
                             */
                            Bitmap bitmapTemp = Bitmap.createBitmap(
                                    loadedBitmap.getWidth(),
                                    loadedBitmap.getHeight(),
                                    loadedBitmap.getConfig());
                            bitmapTemp.recycle();

                            /*
                             * Texture size is ok
                             */
                            LogUtil.d(String.format(Locale.getDefault(), "loaded bitmap: %d x %d",
                                    loadedBitmap.getWidth(), loadedBitmap.getHeight()));
                            publishProgress();

                            Bitmap bitmap = loadedBitmap;
                            if (Preferences.get(mContext.get()).isCropWallpaper() && adjustedRectF != null) {
                                LogUtil.d("rectF: " +adjustedRectF);
                                /*
                                 * Cropping bitmap
                                 */
                                ImageSize targetSize = WallpaperHelper.getTargetSize(mContext.get());

                                int targetWidth = Double.valueOf(
                                        ((double) loadedBitmap.getHeight() / (double) targetSize.getHeight())
                                                * (double) targetSize.getWidth()).intValue();

                                bitmap = Bitmap.createBitmap(
                                        targetWidth,
                                        loadedBitmap.getHeight(),
                                        loadedBitmap.getConfig());
                                Paint paint = new Paint();
                                paint.setFilterBitmap(true);
                                paint.setAntiAlias(true);
                                paint.setDither(true);

                                Canvas canvas = new Canvas(bitmap);
                                canvas.drawBitmap(loadedBitmap, null, adjustedRectF, paint);

                                float scale = (float) targetSize.getHeight() / (float) bitmap.getHeight();
                                if (scale < 1f) {
                                    LogUtil.d("bitmap size is bigger than screen resolution, resizing bitmap");
                                    int resizedWidth = Float.valueOf((float) bitmap.getWidth() * scale).intValue();
                                    bitmap = Bitmap.createScaledBitmap(bitmap, resizedWidth, targetSize.getHeight(), true);
                                }
                            }

                            /*
                             * Final bitmap generated
                             */
                            LogUtil.d(String.format(Locale.getDefault(), "generated bitmap: %d x %d ",
                                    bitmap.getWidth(), bitmap.getHeight()));

                            if (mApply == Apply.HOMESCREEN_LOCKSCREEN) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    WallpaperManager.getInstance(mContext.get().getApplicationContext()).setBitmap(
                                            bitmap, null, true, WallpaperManager.FLAG_LOCK | WallpaperManager.FLAG_SYSTEM);
                                    return true;
                                }
                            }

                            if (mApply == Apply.HOMESCREEN) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    WallpaperManager.getInstance(mContext.get().getApplicationContext()).setBitmap(
                                            bitmap, null, true, WallpaperManager.FLAG_SYSTEM);
                                    return true;
                                }

                                WallpaperManager.getInstance(mContext.get().getApplicationContext()).setBitmap(bitmap);
                                return true;
                            }

                            if (mApply == Apply.LOCKSCREEN) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    WallpaperManager.getInstance(mContext.get().getApplicationContext()).setBitmap(
                                            bitmap, null, true, WallpaperManager.FLAG_LOCK);
                                    return true;
                                }
                            }
                        } catch (OutOfMemoryError e) {
                            LogUtil.e("loaded bitmap is too big, resizing it ...");
                            /*
                             * Texture size is too big
                             * Resizing bitmap
                             */

                            double scale = 1 - (0.1 * call);
                            int scaledWidth = Double.valueOf(adjustedSize.getWidth() * scale).intValue();
                            int scaledHeight = Double.valueOf(adjustedSize.getHeight() * scale).intValue();

                            adjustedRectF = WallpaperHelper.getScaledRectF(adjustedRectF,
                                    (float) scale, (float) scale);
                            adjustedSize = new ImageSize(scaledWidth, scaledHeight);
                        }
                    }

                    /*
                     * Continue to next iteration
                     */
                    call++;
                } while (call <= 5 && !isCancelled());
                return false;
            } catch (Exception e) {
                LogUtil.e(Log.getStackTraceString(e));
                return false;
            }
        }
        return false;
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
        if (mContext.get() == null) return;
        if (mContext.get() instanceof Activity) {
            if (((Activity) mContext.get()).isFinishing())
                return;
        }

        mDialog.setContent(R.string.wallpaper_applying);
    }

    @Override
    protected void onCancelled(Boolean aBoolean) {
        super.onCancelled(aBoolean);
        if (mContext.get() == null) return;
        if (mContext.get() instanceof Activity) {
            if (((Activity) mContext.get()).isFinishing())
                return;
        }

        Toast.makeText(mContext.get(), R.string.wallpaper_apply_cancelled,
                Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (mContext.get() == null) return;
        if (mContext.get() instanceof Activity) {
            if (((Activity) mContext.get()).isFinishing())
                return;
        }

        if (mDialog != null && mDialog.isShowing()) {
            mDialog.dismiss();
        }

        if (aBoolean) {
            CafeBar.builder(mContext.get())
                    .theme(Preferences.get(mContext.get()).isDarkTheme() ? CafeBarTheme.LIGHT : CafeBarTheme.DARK)
                    .contentTypeface(TypefaceHelper.getRegular(mContext.get()))
                    .floating(true)
                    .fitSystemWindow()
                    .content(R.string.wallpaper_applied)
                    .show();
        } else {
            Toast.makeText(mContext.get(), R.string.wallpaper_apply_failed,
                    Toast.LENGTH_LONG).show();
        }
    }

    public enum Apply {
        LOCKSCREEN,
        HOMESCREEN,
        HOMESCREEN_LOCKSCREEN
    }
}
 public class WallpaperPropertiesLoaderTask extends AsyncTask<Void, Void, Boolean> {

    private Wallpaper mWallpaper;
    private WeakReference<Callback> mCallback;
    private final WeakReference<Context> mContext;

    private WallpaperPropertiesLoaderTask(Context context) {
        mContext = new WeakReference<>(context);
    }

    public WallpaperPropertiesLoaderTask wallpaper(Wallpaper wallpaper) {
        mWallpaper = wallpaper;
        return this;
    }

    public WallpaperPropertiesLoaderTask callback(@Nullable Callback callback) {
        mCallback = new WeakReference<>(callback);
        return this;
    }

    public AsyncTask start() {
        return start(SERIAL_EXECUTOR);
    }

    public AsyncTask start(@NonNull Executor executor) {
        return executeOnExecutor(executor);
    }

    public static WallpaperPropertiesLoaderTask prepare(@NonNull Context context) {
        return new WallpaperPropertiesLoaderTask(context);
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        while (!isCancelled()) {
            try {
                Thread.sleep(1);
                if (mWallpaper == null) return false;

                if (mWallpaper.getDimensions() != null &&
                        mWallpaper.getMimeType() != null &&
                        mWallpaper.getSize() > 0) {
                    return false;
                }

                final BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;

                URL url = new URL(mWallpaper.getUrl());
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(15000);

                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    InputStream stream = connection.getInputStream();
                    BitmapFactory.decodeStream(stream, null, options);

                    ImageSize imageSize = new ImageSize(options.outWidth, options.outHeight);
                    mWallpaper.setDimensions(imageSize);
                    mWallpaper.setMimeType(options.outMimeType);

                    int contentLength = connection.getContentLength();
                    if (contentLength > 0) {
                        mWallpaper.setSize(contentLength);
                    }

                    Database.get(mContext.get()).updateWallpaper(mWallpaper);
                    stream.close();
                    return true;
                }
                return false;
            } catch (Exception e) {
                LogUtil.e(Log.getStackTraceString(e));
                return false;
            }
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (aBoolean && mContext.get() != null && !((AppCompatActivity) mContext.get()).isFinishing()) {
            if (mWallpaper.getSize() <= 0) {
                File target = ImageLoader.getInstance().getDiskCache().get(mWallpaper.getUrl());
                if (target.exists()) {
                    mWallpaper.setSize((int) target.length());
                }
            }
        }

        if (mCallback != null && mCallback.get() != null) {
            mCallback.get().onPropertiesReceived(mWallpaper);
        }
    }

    public interface Callback {
        void onPropertiesReceived(Wallpaper wallpaper);
    }
}
 public class WallpaperPaletteLoaderTask {

    private Callback mCallback;
    private Bitmap mBitmap;

    private WallpaperPaletteLoaderTask(Bitmap bitmap) {
        mBitmap = bitmap;
    }

    public WallpaperPaletteLoaderTask callback(@Nullable Callback callback) {
        mCallback = callback;
        return this;
    }

    public AsyncTask start() {
        if (mBitmap == null) {
            LogUtil.e("PaletteLoader cancelled, bitmap is null");
            return null;
        }

        try {
            return Palette.from(mBitmap).generate(palette -> {
                int dominant = palette.getDominantColor(0);
                int vibrant = palette.getVibrantColor(0);
                int vibrantLight = palette.getLightVibrantColor(0);
                int vibrantDark = palette.getDarkVibrantColor(0);
                int muted = palette.getMutedColor(0);
                int mutedLight = palette.getLightMutedColor(0);
                int mutedDark = palette.getDarkMutedColor(0);

                ColorPalette colorPalette = new ColorPalette();
                colorPalette.add(dominant);
                colorPalette.add(vibrant);
                colorPalette.add(vibrantLight);
                colorPalette.add(vibrantDark);
                colorPalette.add(muted);
                colorPalette.add(mutedLight);
                colorPalette.add(mutedDark);
                if (mCallback != null) {
                    mCallback.onPaletteGenerated(colorPalette);
                }
            });
        } catch (Exception ignored) {}
        return null;
    }

    public static WallpaperPaletteLoaderTask with(Bitmap bitmap) {
        return new WallpaperPaletteLoaderTask(bitmap);
    }

    public interface Callback {
        void onPaletteGenerated(ColorPalette palette);
    }
}
 public class Popup {

    private ListPopupWindow mPopupWindow;
    private PopupAdapter mAdapter;

    private Popup(Builder builder) {
        mPopupWindow = new ListPopupWindow(builder.mContext);
        mAdapter = new PopupAdapter(builder.mContext, builder.mItems);


        int width = getMeasuredWidth(builder.mContext);
        mPopupWindow.setContentWidth(width);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Drawable drawable = mPopupWindow.getBackground();
            if (drawable != null) {
                drawable.setColorFilter(ColorHelper.getAttributeColor(
                        builder.mContext, R.attr.card_background), PorterDuff.Mode.SRC_IN);
            }
        } else {
            mPopupWindow.setBackgroundDrawable(new ColorDrawable(
                    ColorHelper.getAttributeColor(builder.mContext, R.attr.card_background)));
        }

        mPopupWindow.setAnchorView(builder.mTo);
        mPopupWindow.setAdapter(mAdapter);
        mPopupWindow.setOnItemClickListener((adapterView, view, i, l) -> {
            if (builder.mCallback != null) {
                builder.mCallback.onClick(this, i);
                return;
            }

            mPopupWindow.dismiss();
        });
    }

    public void show() {
        if (mAdapter.getCount() == 0) {
            LogUtil.e("Popup size = 0, show() ignored");
            return;
        }
        mPopupWindow.show();
    }

    public void dismiss() {
        if (mPopupWindow.isShowing())
            mPopupWindow.dismiss();
    }

    public List<PopupItem> getItems() {
        return mAdapter.getItems();
    }

    public void updateItem(int position, PopupItem item) {
        mAdapter.updateItem(position, item);
    }

    public void removeItem(int position) {
        mAdapter.removeItem(position);
    }

    public static Builder Builder(@NonNull Context context) {
        return new Builder(context);
    }

    private int getMeasuredWidth(@NonNull Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metrics);

        int maxWidth = context.getResources().getDimensionPixelSize(R.dimen.popup_max_width);
        int minWidth = context.getResources().getDimensionPixelSize(R.dimen.popup_min_width);
        String longestText = "";
        for (PopupItem item : mAdapter.getItems()) {
            if (item.getTitle().length() > longestText.length())
                longestText = item.getTitle();
        }

        int padding = context.getResources().getDimensionPixelSize(R.dimen.content_margin);
        int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size_small);
        TextView textView = new TextView(context);
        textView.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        textView.setTypeface(TypefaceHelper.getRegular(context));
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
                .getDimension(R.dimen.text_content_subtitle));
        textView.setPadding(padding + iconSize + padding, 0, padding, 0);
        textView.setText(longestText);

        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        textView.measure(widthMeasureSpec, heightMeasureSpec);

        int measuredWidth = textView.getMeasuredWidth() + padding;
        if (measuredWidth <= minWidth) {
            return minWidth;
        }

        if (measuredWidth >= minWidth && measuredWidth <= maxWidth) {
            return measuredWidth;
        }
        return maxWidth;
    }

    public static class Builder {

        private final Context mContext;
        private Callback mCallback;
        private View mTo;
        private List<PopupItem> mItems;

        private Builder(Context context) {
            mContext = context;
            mItems = new ArrayList<>();
        }

        public Builder to(@Nullable View to) {
            mTo = to;
            return this;
        }

        public Builder list(@NonNull List<PopupItem> items) {
            mItems = items;
            return this;
        }

        public Builder callback(@Nullable Callback callback) {
            mCallback = callback;
            return this;
        }

        public Popup build() {
            return new Popup(this);
        }

        public void show() {
            build().show();
        }
    }

    class PopupAdapter extends BaseAdapter {

        private List<PopupItem> mItems;
        private final Context mContext;

        PopupAdapter(@NonNull Context context, @NonNull List<PopupItem> items) {
            mContext = context;
            mItems = items;
        }

        @Override
        public int getCount() {
            return mItems.size();
        }

        @Override
        public PopupItem getItem(int position) {
            return mItems.get(position);
        }

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

        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            ViewHolder holder;
            if (view == null) {
                view = View.inflate(mContext, R.layout.popup_item_list, null);
                holder = new ViewHolder(view);
                view.setTag(holder);
            } else {
                holder = (ViewHolder) view.getTag();
            }

            PopupItem item = mItems.get(position);
            holder.checkBox.setVisibility(View.GONE);
            if (item.isShowCheckbox()) {
                holder.checkBox.setChecked(item.getCheckboxValue());
                holder.checkBox.setVisibility(View.VISIBLE);
            }

            int color = ColorHelper.getAttributeColor(mContext, android.R.attr.textColorPrimary);
            if (item.isSelected()) {
                color = ColorHelper.getAttributeColor(mContext, R.attr.colorAccent);
            }

            if (item.getIcon() != 0) {
                Drawable drawable = DrawableHelper.getTintedDrawable(mContext, item.getIcon(), color);
                holder.title.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
            }

            holder.title.setText(item.getTitle());
            holder.title.setTextColor(color);
            return view;
        }

        class ViewHolder {

            @BindView(R2.id.checkbox)
            AppCompatCheckBox checkBox;
            @BindView(R2.id.title)
            TextView title;

            ViewHolder(@NonNull View view) {
                ButterKnife.bind(this, view);
            }
        }

        List<PopupItem> getItems() {
            return mItems;
        }

        void updateItem(int position, PopupItem item) {
            mItems.set(position, item);
            notifyDataSetChanged();
        }

        void removeItem(int position) {
            mItems.remove(position);
            notifyDataSetChanged();
        }
    }

    public interface Callback {
        void onClick(Popup popup, int position);
    }
}
 public abstract class Extras {

    public static final String TAG_COLLECTION = "collection";
    public static final String TAG_WALLPAPERS = "wallpapers";
    public static final String TAG_LATEST = "latest";
    public static final String TAG_CATEGORIES = "categories";
    public static final String TAG_WALLPAPER_SEARCH = "wallpaperSearch";
    public static final String TAG_FAVORITES = "favorites";
    public static final String TAG_SETTINGS = "settings";
    public static final String TAG_ABOUT = "about";

    public static final String EXTRA_URL = "url";
    public static final String EXTRA_POSITION = "position";
    public static final String EXTRA_IMAGE = "image";
    public static final String EXTRA_RESUMED = "resumed";
    public static final String EXTRA_FRAGMENT_ID = "fragmentId";
    public static final String EXTRA_CATEGORY = "category";
    public static final String EXTRA_COUNT = "count";
    public static final String EXTRA_ITEM = "item";

    public static final String EXTRA_KEY = "key";
    public static final String EXTRA_PRODUCT_ID = "productId";
    public static final String EXTRA_TYPE = "type";

    public static final int TYPE_CONTRIBUTORS = 1;
    public static final int TYPE_DASHBOARD_CONTRIBUTORS = 2;
    public static final int TYPE_DASHBOARD_TRANSLATOR = 3;

    public static final int ID_CATEGORY_WALLPAPERS = 0;
    public static final int ID_WALLPAPER_SEARCH = 1;
}
 public class Tooltip {

    private final ListPopupWindow mPopupWindow;
    private final Builder mBuilder;
    private boolean mCheckboxState = false;

    private Tooltip(Builder builder) {
        mBuilder = builder;

        mPopupWindow = new ListPopupWindow(mBuilder.mContext);
        mPopupWindow.setContentWidth(getMeasuredWidth(builder.mContext));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Drawable drawable = mPopupWindow.getBackground();
            if (drawable != null) {
                drawable.setColorFilter(ColorHelper.getAttributeColor(
                        builder.mContext, R.attr.card_background), PorterDuff.Mode.SRC_IN);
            }
        } else {
            mPopupWindow.setBackgroundDrawable(new ColorDrawable(
                    ColorHelper.getAttributeColor(builder.mContext, R.attr.card_background)));
        }

        mPopupWindow.setListSelector(new ColorDrawable(Color.TRANSPARENT));
        mPopupWindow.setAnchorView(mBuilder.mTo);
        mPopupWindow.setForceIgnoreOutsideTouch(true);
        mPopupWindow.setAdapter(new TooltipAdapter(mBuilder.mContext, this));
    }

    public boolean getCheckboxState() {
        return mCheckboxState;
    }

    public void show() {
        try {
            mPopupWindow.show();
        } catch (Exception e) {
            LogUtil.e(Log.getStackTraceString(e));
        }
    }

    public void dismiss() {
        if (mPopupWindow.isShowing())
            mPopupWindow.dismiss();
    }

    private int getMeasuredWidth(@NonNull Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metrics);

        int maxWidth = context.getResources().getDimensionPixelSize(R.dimen.tooltip_max_width);
        int minWidth = context.getResources().getDimensionPixelSize(R.dimen.tooltip_min_width);
        String longestText = mBuilder.mContent;
        if (mBuilder.mContent.length() < mBuilder.mDesc.length()) {
            longestText = mBuilder.mDesc;
        }

        int padding = context.getResources().getDimensionPixelSize(R.dimen.content_margin);
        TextView textView = new TextView(context);
        textView.setPadding(padding, 0, padding, 0);
        textView.setTypeface(TypefaceHelper.getRegular(context));
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
                .getDimension(R.dimen.text_content_subtitle));
        textView.setText(longestText);

        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        textView.measure(widthMeasureSpec, heightMeasureSpec);

        int measuredWidth = textView.getMeasuredWidth() + padding;
        if (measuredWidth <= minWidth) {
            return minWidth;
        }

        if (measuredWidth >= minWidth && measuredWidth <= maxWidth) {
            return measuredWidth;
        }
        return maxWidth;
    }

    public static Builder Builder(@NonNull Context context) {
        return new Builder(context);
    }

    public static class Builder {

        private final Context mContext;
        private View mTo;
        private String mContent;
        private String mDesc;
        private int mDescIcon;
        private String mButton;
        private Callback mCallback;
        private boolean mCancelable;
        private boolean mIsDontShowAgainVisible;

        private Builder(@NonNull Context context) {
            mContext = context;
            mContent = "";
            mDescIcon = 0;
            mCancelable = true;
            mButton = mContext.getResources().getString(android.R.string.ok);
            mIsDontShowAgainVisible = false;
        }

        public Builder to(@NonNull View to) {
            mTo = to;
            return this;
        }

        public Builder cancelable(boolean cancelable) {
            mCancelable = cancelable;
            return this;
        }

        public Builder content(@StringRes int res) {
            mContent = mContext.getResources().getString(res);
            return this;
        }

        public Builder desc(@StringRes int res) {
            mDesc = mContext.getResources().getString(res);
            return this;
        }

        public Builder descIcon(@DrawableRes int res) {
            mDescIcon = res;
            return this;
        }

        public Builder buttonText(@StringRes int res) {
            mButton = mContext.getResources().getString(res);
            return this;
        }

        public Builder buttonCallback(@Nullable Callback callback) {
            mCallback = callback;
            return this;
        }

        public Builder visibleDontShowAgain(boolean show) {
            mIsDontShowAgainVisible = show;
            return this;
        }

        public Tooltip build() {
            return new Tooltip(this);
        }

        public void show() {
            build().show();
        }
    }

    class TooltipAdapter extends BaseAdapter {

        private final Context mContext;
        private final Tooltip mTooltip;

        TooltipAdapter(Context context, Tooltip tooltip) {
            mContext = context;
            mTooltip = tooltip;
        }

        @Override
        public int getCount() {
            return 1;
        }

        @Override
        public String getItem(int position) {
            return mBuilder.mContent;
        }

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

        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            if (view == null) {
                view = View.inflate(mContext, R.layout.tooltips_popup, null);
            }

            TextView content = view.findViewById( R.id.content);
            TextView desc = view.findViewById( R.id.desc);
            AppCompatCheckBox checkBox = view.findViewById( R.id.checkbox);
            TextView button = view.findViewById( R.id.button);

            content.setText(mBuilder.mContent);
            button.setText(mBuilder.mButton);

            if (mBuilder.mDesc != null) {
                desc.setVisibility(View.VISIBLE);
                desc.setText(mBuilder.mDesc);

                if (mBuilder.mDescIcon != 0) {
                    int color = ColorHelper.getAttributeColor(mContext, android.R.attr.textColorPrimary);
                    Drawable drawable = DrawableHelper.getTintedDrawable(mContext, mBuilder.mDescIcon, color);
                    desc.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null);
                }
            }


            checkBox.setVisibility(mBuilder.mIsDontShowAgainVisible ? View.VISIBLE : View.GONE);
            checkBox.setOnCheckedChangeListener((compoundButton, b) -> mCheckboxState = b);

            button.setOnClickListener(v -> {
                if (mBuilder.mCallback != null) {
                    mBuilder.mCallback.onButtonClick(mTooltip);
                    return;
                }

                mTooltip.dismiss();
            });
            return view;
        }
    }

    public interface Callback {
        void onButtonClick(Tooltip tooltip);
    }
}
 public class WallpaperDownloader {

    private final Context mContext;
    private Wallpaper mWallpaper;

    private WallpaperDownloader(Context context) {
        mContext = context;
    }

    public WallpaperDownloader wallpaper(@NonNull Wallpaper wallpaper) {
        mWallpaper = wallpaper;
        return this;
    }

    public void start() {
        String fileName = mWallpaper.getName() +"."+ WallpaperHelper.getFormat(mWallpaper.getMimeType());
        File directory = WallpaperHelper.getDefaultWallpapersDirectory(mContext);
        File target = new File(directory, fileName);
        if (!directory.exists()) {
            if (!directory.mkdirs()) {
                LogUtil.e("Unable to create directory " +directory.toString());
                showCafeBar(R.string.wallpaper_download_failed);
                return;
            }
        }

        if (WallpaperHelper.isWallpaperSaved(mContext, mWallpaper)) {
            CafeBar.builder(mContext)
                    .theme(Preferences.get(mContext).isDarkTheme() ? CafeBarTheme.LIGHT : CafeBarTheme.DARK)
                    .floating(true)
                    .fitSystemWindow()
                    .duration(CafeBar.Duration.MEDIUM)
                    .typeface(TypefaceHelper.getRegular(mContext), TypefaceHelper.getBold(mContext))
                    .content(R.string.wallpaper_already_downloaded)
                    .neutralText(R.string.open)
                    .onNeutral(cafeBar -> {
                        Uri uri = FileHelper.getUriFromFile(mContext, mContext.getPackageName(), target);
                        if (uri == null) {
                            cafeBar.dismiss();
                            return;
                        }

                        try {
                            mContext.startActivity(new Intent()
                                    .setAction(Intent.ACTION_VIEW)
                                    .setDataAndType(uri, "image/*")
                                    .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION));
                        } catch (ActivityNotFoundException e) {
                            LogUtil.e(Log.getStackTraceString(e));
                        }

                        cafeBar.dismiss();
                    })
                    .show();
            return;
        }

        if (!URLUtil.isValidUrl(mWallpaper.getUrl())) {
            LogUtil.e("Download: wallpaper url is not valid");
            return;
        }

        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mWallpaper.getUrl()));
        request.setMimeType(mWallpaper.getMimeType());
        request.setTitle(fileName);
        request.setDescription(mContext.getResources().getString(R.string.wallpaper_downloading));
        request.allowScanningByMediaScanner();
        request.setVisibleInDownloadsUi(false);
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setDestinationUri(Uri.fromFile(target));

        DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);

        try {
            if (downloadManager != null) {
                downloadManager.enqueue(request);
                return;
            }

            LogUtil.e("Download: download manager is null");
        } catch (IllegalArgumentException e) {
            LogUtil.e(Log.getStackTraceString(e));
            return;
        }

        showCafeBar(R.string.wallpaper_downloading);
    }

    private void showCafeBar(int res) {
        CafeBar.builder(mContext)
                .theme(Preferences.get(mContext).isDarkTheme() ? CafeBarTheme.LIGHT : CafeBarTheme.DARK)
                .contentTypeface(TypefaceHelper.getRegular(mContext))
                .content(res)
                .floating(true)
                .fitSystemWindow()
                .show();
    }

    public static WallpaperDownloader prepare(@NonNull Context context) {
        return new WallpaperDownloader(context);
    }
}

import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.transition.Transition;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.danimahardhika.android.helpers.animation.AnimationHelper;
import com.danimahardhika.android.helpers.core.ColorHelper;
import com.danimahardhika.android.helpers.core.DrawableHelper;
import com.danimahardhika.android.helpers.core.ViewHelper;
import com.danimahardhika.android.helpers.core.WindowHelper;
import com.danimahardhika.android.helpers.permission.PermissionCode;
import com.danimahardhika.android.helpers.permission.PermissionHelper;
import com.dm.wallpaper.board.R;
import com.dm.wallpaper.board.R2;
import com.dm.wallpaper.board.adapters.WallpaperDetailsAdapter;
import com.dm.wallpaper.board.applications.WallpaperBoardApplication;
import com.dm.wallpaper.board.databases.Database;
import com.dm.wallpaper.board.helpers.LocaleHelper;
import com.dm.wallpaper.board.helpers.TapIntroHelper;
import com.dm.wallpaper.board.items.Category;
import com.dm.wallpaper.board.items.ColorPalette;
import com.dm.wallpaper.board.items.PopupItem;
import com.dm.wallpaper.board.items.Wallpaper;
import com.dm.wallpaper.board.items.WallpaperProperty;
import com.dm.wallpaper.board.preferences.Preferences;
import com.dm.wallpaper.board.tasks.LocalFavoritesRestoreTask;
import com.dm.wallpaper.board.tasks.WallpaperApplyTask;
import com.dm.wallpaper.board.tasks.WallpaperPropertiesLoaderTask;
import com.dm.wallpaper.board.tasks.WallpaperPaletteLoaderTask;
import com.dm.wallpaper.board.utils.Popup;
import com.dm.wallpaper.board.utils.Extras;
import com.dm.wallpaper.board.utils.ImageConfig;
import com.danimahardhika.android.helpers.core.utils.LogUtil;
import com.dm.wallpaper.board.utils.Tooltip;
import com.dm.wallpaper.board.utils.WallpaperDownloader;
import com.github.chrisbanes.photoview.PhotoViewAttacher;
import com.kogitune.activitytransition.ActivityTransition;
import com.kogitune.activitytransition.ExitActivityTransition;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;

    }

    @Override
    protected void attachBaseContext(Context newBase) {
        LocaleHelper.setLocale(newBase);
        super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent != null && intent.getExtras() != null) {
            this.setIntent(intent);
            String url = "";
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                url = bundle.getString(Extras.EXTRA_URL);
            }

            Wallpaper wallpaper = Database.get(this).getWallpaper(url);
            if (wallpaper == null) {
                return;
            }

            mWallpaper = wallpaper;
            loadWallpaper(mWallpaper.getThumbUrl());
            mSlidingLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (mWallpaper != null) {
            outState.putString(Extras.EXTRA_URL, mWallpaper.getUrl());
        }

        outState.putBoolean(Extras.EXTRA_RESUMED, true);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onDestroy() {
        if (Preferences.get(this).isCropWallpaper()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
        }

        ImageLoader.getInstance().cancelDisplayTask(mImageView);
        WallpaperBoardApplication.sIsClickable = true;
        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        if (mSlidingLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
            mSlidingLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
            return;
        }

        if (mTooltip != null) {
            mTooltip.dismiss();
            mTooltip = null;
        }

        if (mHandler != null && mRunnable != null)
            mHandler.removeCallbacks(mRunnable);

        if (mExitTransition != null) {
            mExitTransition.exit(this);
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.back) {
            onBackPressed();
        } else if (id == R.id.menu_preview) {
            if (mTooltip != null) {
                mTooltip.dismiss();
            }

            if (mProgress.getVisibility() == View.GONE) {
                loadWallpaper(mWallpaper.getUrl());
            }
        } else if (id == R.id.menu_save) {
            if (PermissionHelper.isStorageGranted(this)) {
                WallpaperDownloader.prepare(this)
                        .wallpaper(mWallpaper)
                        .start();
                return;
            }

            PermissionHelper.requestStorage(this);
        } else if (id == R.id.menu_apply) {
            Popup popup = Popup.Builder(this)
                    .to(view)
                    .list(PopupItem.getApplyItems(this))
                    .callback((applyPopup, position) -> {
                        PopupItem item = applyPopup.getItems().get(position);
                        if (item.getType() == PopupItem.Type.WALLPAPER_CROP) {
                            Preferences.get(this).setCropWallpaper(!item.getCheckboxValue());
                            item.setCheckboxValue(Preferences.get(this).isCropWallpaper());

                            applyPopup.updateItem(position, item);
                            if (Preferences.get(WallpaperBoardPreviewActivity.this).isCropWallpaper()) {
                                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                return;
                            }

                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
                            return;
                        } else if (item.getType() == PopupItem.Type.LOCKSCREEN) {
                            RectF rectF = null;
                            if (Preferences.get(WallpaperBoardPreviewActivity.this).isCropWallpaper()) {
                                if (mAttacher != null)
                                    rectF = mAttacher.getDisplayRect();
                            }


                            WallpaperApplyTask.prepare(this)
