/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.wallpaper.asset;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.LruCache;
import android.widget.ImageView;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityManagerCompat;

import java.util.Objects;

/**
 * Implementation of {@link Asset} that wraps another {@link Asset} but keeps an LRU cache of
 * bitmaps generated by {@link #decodeBitmap(int, int, BitmapReceiver)} to avoid having to decode
 * the same bitmap multiple times.
 * The cache key is the wrapped Asset and the target Width and Height requested, so that we only
 * reuse bitmaps of the same size.
 */
public class BitmapCachingAsset extends Asset {

    private static class CacheKey {
        final Asset mAsset;
        final int mWidth;
        final int mHeight;
        final boolean mRtl;
        final Rect mRect;

        CacheKey(Asset asset, int width, int height) {
            this(asset, width, height, false, null);
        }

        CacheKey(Asset asset, int width, int height, boolean rtl, Rect rect) {
            mAsset = asset;
            mWidth = width;
            mHeight = height;
            mRtl = rtl;
            mRect = rect;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mAsset, mWidth, mHeight);
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof CacheKey
                    && (Objects.equals(this.mAsset, ((CacheKey) obj).mAsset))
                    && ((CacheKey) obj).mWidth == this.mWidth
                    && ((CacheKey) obj).mHeight == this.mHeight
                    && ((CacheKey) obj).mRtl == this.mRtl
                    && (Objects.equals(this.mRect, ((CacheKey) obj).mRect));
        }
    }

    private static int cacheSize = 100 * 1024 * 1024; // 100MiB
    private static LruCache<CacheKey, Bitmap> sCache = new LruCache<CacheKey, Bitmap>(cacheSize) {
        @Override protected int sizeOf(CacheKey key, Bitmap value) {
            return value.getByteCount();
        }
    };

    private final boolean mIsLowRam;
    private final Asset mOriginalAsset;

    public BitmapCachingAsset(Context context, Asset originalAsset) {
        mOriginalAsset = originalAsset instanceof BitmapCachingAsset
                ? ((BitmapCachingAsset) originalAsset).mOriginalAsset : originalAsset;
        mIsLowRam = ActivityManagerCompat.isLowRamDevice(
                (ActivityManager) context.getApplicationContext().getSystemService(
                        Context.ACTIVITY_SERVICE));
    }

    @Override
    public void decodeBitmap(int targetWidth, int targetHeight, BitmapReceiver receiver) {
        // Skip the cache in low ram devices
        if (mIsLowRam) {
            mOriginalAsset.decodeBitmap(targetWidth, targetHeight, receiver::onBitmapDecoded);
            return;
        }
        CacheKey key = new CacheKey(mOriginalAsset, targetWidth, targetHeight);
        Bitmap cached = sCache.get(key);
        if (cached != null) {
            receiver.onBitmapDecoded(cached);
        } else {
            mOriginalAsset.decodeBitmap(targetWidth, targetHeight, bitmap -> {
                if (bitmap != null) {
                    sCache.put(key, bitmap);
                }
                receiver.onBitmapDecoded(bitmap);
            });
        }
    }

    @Override
    public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
            boolean shouldAdjustForRtl, BitmapReceiver receiver) {
        // Skip the cache in low ram devices
        if (mIsLowRam) {
            mOriginalAsset.decodeBitmapRegion(rect, targetWidth, targetHeight, shouldAdjustForRtl,
                    receiver);
            return;
        }
        CacheKey key = new CacheKey(mOriginalAsset, targetWidth, targetHeight, shouldAdjustForRtl,
                rect);
        Bitmap cached = sCache.get(key);
        if (cached != null) {
            receiver.onBitmapDecoded(cached);
        } else {
            mOriginalAsset.decodeBitmapRegion(rect, targetWidth, targetHeight, shouldAdjustForRtl,
                    bitmap -> {
                        if (bitmap != null) {
                            sCache.put(key, bitmap);
                        }
                        receiver.onBitmapDecoded(bitmap);
                    });
        }
    }

    @Override
    public void decodeRawDimensions(@Nullable Activity activity, DimensionsReceiver receiver) {
        mOriginalAsset.decodeRawDimensions(activity, receiver);
    }

    @Override
    public boolean supportsTiling() {
        return mOriginalAsset.supportsTiling();
    }

    @Override
    public void loadPreviewImage(Activity activity, ImageView imageView, int placeholderColor) {
        // Honor the original Asset's preview image loading
        mOriginalAsset.loadPreviewImage(activity, imageView, placeholderColor);
    }
}
