/*
 * Copyright (C) 2014 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.bitmap.drawable;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;

import com.android.bitmap.BitmapCache;

/**
 * Custom BasicBitmapDrawable implementation for circular images.
 *
 * This draws all bitmaps as a circle with an optional border stroke.
 */
public class CircularBitmapDrawable extends ExtendedBitmapDrawable {
    private static Matrix sMatrix = new Matrix();

    private final Paint mBitmapPaint = new Paint();
    private final Paint mBorderPaint = new Paint();

    private float mBorderWidth;
    private Bitmap mShaderBitmap;

    public CircularBitmapDrawable(Resources res,
            BitmapCache cache, boolean limitDensity) {
        this(res, cache, limitDensity, null);
    }

    public CircularBitmapDrawable(Resources res,
            BitmapCache cache, boolean limitDensity, ExtendedOptions opts) {
        super(res, cache, limitDensity, opts);

        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setFilterBitmap(true);
        mBitmapPaint.setDither(true);

        mBorderPaint.setColor(Color.TRANSPARENT);
        mBorderPaint.setStyle(Style.STROKE);
        mBorderPaint.setStrokeWidth(mBorderWidth);
        mBorderPaint.setAntiAlias(true);
    }

    /**
     * Set the border stroke width of this drawable.
     */
    public void setBorderWidth(final float borderWidth) {
        final boolean changed = mBorderPaint.getStrokeWidth() != borderWidth;
        mBorderPaint.setStrokeWidth(borderWidth);
        mBorderWidth = borderWidth;

        if (changed) {
            invalidateSelf();
        }
    }

    /**
     * Set the border stroke color of this drawable. Set to {@link Color#TRANSPARENT} to disable.
     */
    public void setBorderColor(final int color) {
        final boolean changed = mBorderPaint.getColor() != color;
        mBorderPaint.setColor(color);

        if (changed) {
            invalidateSelf();
        }
    }

    @Override
    protected void onDrawBitmap(final Canvas canvas, final Rect src,
            final Rect dst) {
        onDrawCircularBitmap(getBitmap().bmp, canvas, src, dst, 1f);
    }

    @Override
    protected void onDrawPlaceholderOrProgress(final Canvas canvas,
            final TileDrawable drawable) {
        BitmapDrawable placeholder = (BitmapDrawable) drawable.getInnerDrawable();
        Bitmap bitmap = placeholder.getBitmap();
        float alpha = placeholder.getPaint().getAlpha() / 255f;
        sRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
        onDrawCircularBitmap(bitmap, canvas, sRect, getBounds(), alpha);
    }

    /**
     * Call this method with a given bitmap to draw it onto the given canvas, masked by a circular
     * BitmapShader.
     */
    protected void onDrawCircularBitmap(final Bitmap bitmap, final Canvas canvas,
            final Rect src, final Rect dst) {
        onDrawCircularBitmap(bitmap, canvas, src, dst, 1f);
    }

    /**
     * Call this method with a given bitmap to draw it onto the given canvas, masked by a circular
     * BitmapShader. The alpha parameter is the value from 0f to 1f to attenuate the alpha by.
     */
    protected void onDrawCircularBitmap(final Bitmap bitmap, final Canvas canvas,
            final Rect src, final Rect dst, final float alpha) {
        // Draw bitmap through shader first.
        BitmapShader shader = (BitmapShader) mBitmapPaint.getShader();
        if (shader == null || mShaderBitmap != bitmap) {
          shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
          mShaderBitmap = bitmap;
        }

        sMatrix.reset();
        // Fit bitmap to bounds.
        float scale = Math.max((float) dst.width() / src.width(),
                (float) dst.height() / src.height());
        sMatrix.postScale(scale, scale);
        // Translate bitmap to dst bounds.
        sMatrix.postTranslate(dst.left, dst.top);
        shader.setLocalMatrix(sMatrix);
        mBitmapPaint.setShader(shader);

        int oldAlpha = mBitmapPaint.getAlpha();
        mBitmapPaint.setAlpha((int) (oldAlpha * alpha));
        canvas.drawCircle(dst.centerX(), dst.centerY(), dst.width() / 2,
                mBitmapPaint);
        mBitmapPaint.setAlpha(oldAlpha);

        // Then draw the border.
        canvas.drawCircle(dst.centerX(), dst.centerY(),
                dst.width() / 2f - mBorderWidth / 2, mBorderPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        super.setAlpha(alpha);

        final int old = mBitmapPaint.getAlpha();
        mBitmapPaint.setAlpha(alpha);
        if (alpha != old) {
            invalidateSelf();
        }
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        super.setColorFilter(cf);
        mPaint.setColorFilter(cf);
    }
}
