/*
 * Copyright (C) 2015 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.setupwizardlib;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;

import java.lang.ref.SoftReference;

/**
 * This class draws the GLIF pattern used as the status bar background for phones and background for
 * tablets in GLIF layout.
 */
public class GlifPatternDrawable extends Drawable {
    /*
     * This class essentially implements a simple SVG in Java code, with some special handling of
     * scaling when given different bounds.
     */

    /* static section */

    @SuppressLint("InlinedApi")
    private static final int[] ATTRS_PRIMARY_COLOR = new int[]{ android.R.attr.colorPrimary };

    private static final float VIEWBOX_HEIGHT = 768f;
    private static final float VIEWBOX_WIDTH = 1366f;
    // X coordinate of scale focus, as a fraction of of the width. (Range is 0 - 1)
    private static final float SCALE_FOCUS_X = .146f;
    // Y coordinate of scale focus, as a fraction of of the height. (Range is 0 - 1)
    private static final float SCALE_FOCUS_Y = .228f;

    // Alpha component of the color to be drawn, on top of the grayscale pattern. (Range is 0 - 1)
    private static final float COLOR_ALPHA = .8f;
    // Int version of COLOR_ALPHA. (Range is 0 - 255)
    private static final int COLOR_ALPHA_INT = (int) (COLOR_ALPHA * 255);

    // Cap the bitmap size, such that it won't hurt the performance too much
    // and it won't crash due to a very large scale.
    // The drawable will look blurry above this size.
    // This is a multiplier applied on top of the viewbox size.
    // Resulting max cache size = (1.5 x 1366, 1.5 x 768) = (2049, 1152)
    private static final float MAX_CACHED_BITMAP_SCALE = 1.5f;

    private static final int NUM_PATHS = 7;

    private static SoftReference<Bitmap> sBitmapCache;
    private static Path[] sPatternPaths;
    private static int[] sPatternLightness;

    public static GlifPatternDrawable getDefault(Context context) {
        int colorPrimary = 0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            final TypedArray a = context.obtainStyledAttributes(ATTRS_PRIMARY_COLOR);
            colorPrimary = a.getColor(0, Color.BLACK);
            a.recycle();
        }
        return new GlifPatternDrawable(colorPrimary);
    }

    @VisibleForTesting
    public static void invalidatePattern() {
        sBitmapCache = null;
    }

    /* non-static section */

    private int mColor;
    private Paint mTempPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public GlifPatternDrawable(int color) {
        setColor(color);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        final Rect bounds = getBounds();
        int drawableWidth = bounds.width();
        int drawableHeight = bounds.height();
        Bitmap bitmap = null;
        if (sBitmapCache != null) {
            bitmap = sBitmapCache.get();
        }
        if (bitmap != null) {
            final int bitmapWidth = bitmap.getWidth();
            final int bitmapHeight = bitmap.getHeight();
            // Invalidate the cache if this drawable is bigger and we can still create a bigger
            // cache.
            if (drawableWidth > bitmapWidth
                    && bitmapWidth < VIEWBOX_WIDTH * MAX_CACHED_BITMAP_SCALE) {
                bitmap = null;
            } else if (drawableHeight > bitmapHeight
                    && bitmapHeight < VIEWBOX_HEIGHT * MAX_CACHED_BITMAP_SCALE) {
                bitmap = null;
            }
        }

        if (bitmap == null) {
            // Reset the paint so it can be used to draw the paths in renderOnCanvas
            mTempPaint.reset();

            bitmap = createBitmapCache(drawableWidth, drawableHeight);
            sBitmapCache = new SoftReference<>(bitmap);

            // Reset the paint to so it can be used to draw the bitmap
            mTempPaint.reset();
        }

        canvas.save();
        canvas.clipRect(bounds);

        scaleCanvasToBounds(canvas, bitmap, bounds);
        canvas.drawColor(Color.BLACK);
        mTempPaint.setColor(Color.WHITE);
        canvas.drawBitmap(bitmap, 0, 0, mTempPaint);
        canvas.drawColor(mColor);

        canvas.restore();
    }

    @VisibleForTesting
    public Bitmap createBitmapCache(int drawableWidth, int drawableHeight) {
        float scaleX = drawableWidth / VIEWBOX_WIDTH;
        float scaleY = drawableHeight / VIEWBOX_HEIGHT;
        float scale = Math.max(scaleX, scaleY);
        scale = Math.min(MAX_CACHED_BITMAP_SCALE, scale);


        int scaledWidth = (int) (VIEWBOX_WIDTH * scale);
        int scaledHeight = (int) (VIEWBOX_HEIGHT * scale);

        // Use ALPHA_8 mask to save memory, since the pattern is grayscale only anyway.
        Bitmap bitmap = Bitmap.createBitmap(
                scaledWidth,
                scaledHeight,
                Bitmap.Config.ALPHA_8);
        Canvas bitmapCanvas = new Canvas(bitmap);
        renderOnCanvas(bitmapCanvas, scale);
        return bitmap;
    }

    private void renderOnCanvas(Canvas canvas, float scale) {
        canvas.save();
        canvas.scale(scale, scale);

        mTempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));

        // Draw the pattern by creating the paths, adjusting the colors and drawing them. The path
        // values are extracted from the SVG of the pattern file.

        if (sPatternPaths == null) {
            sPatternPaths = new Path[NUM_PATHS];
            // Lightness values of the pattern, range 0 - 255
            sPatternLightness = new int[] { 10, 40, 51, 66, 91, 112, 130 };

            Path p = sPatternPaths[0] = new Path();
            p.moveTo(1029.4f, 357.5f);
            p.lineTo(1366f, 759.1f);
            p.lineTo(1366f, 0f);
            p.lineTo(1137.7f, 0f);
            p.close();

            p = sPatternPaths[1] = new Path();
            p.moveTo(1138.1f, 0f);
            p.rLineTo(-144.8f, 768f);
            p.rLineTo(372.7f, 0f);
            p.rLineTo(0f, -524f);
            p.cubicTo(1290.7f, 121.6f, 1219.2f, 41.1f, 1178.7f, 0f);
            p.close();

            p = sPatternPaths[2] = new Path();
            p.moveTo(949.8f, 768f);
            p.rCubicTo(92.6f, -170.6f, 213f, -440.3f, 269.4f, -768f);
            p.lineTo(585f, 0f);
            p.rLineTo(2.1f, 766f);
            p.close();

            p = sPatternPaths[3] = new Path();
            p.moveTo(471.1f, 768f);
            p.rMoveTo(704.5f, 0f);
            p.cubicTo(1123.6f, 563.3f, 1027.4f, 275.2f, 856.2f, 0f);
            p.lineTo(476.4f, 0f);
            p.rLineTo(-5.3f, 768f);
            p.close();

            p = sPatternPaths[4] = new Path();
            p.moveTo(323.1f, 768f);
            p.moveTo(777.5f, 768f);
            p.cubicTo(661.9f, 348.8f, 427.2f, 21.4f, 401.2f, 25.4f);
            p.lineTo(323.1f, 768f);
            p.close();

            p = sPatternPaths[5] = new Path();
            p.moveTo(178.44286f, 766.8571f);
            p.lineTo(308.7f, 768f);
            p.cubicTo(381.7f, 604.6f, 481.6f, 344.3f, 562.2f, 0f);
            p.lineTo(0f, 0f);
            p.close();

            p = sPatternPaths[6] = new Path();
            p.moveTo(146f, 0f);
            p.lineTo(0f, 0f);
            p.lineTo(0f, 768f);
            p.lineTo(394.2f, 768f);
            p.cubicTo(327.7f, 475.3f, 228.5f, 201f, 146f, 0f);
            p.close();
        }

        for (int i = 0; i < NUM_PATHS; i++) {
            // Color is 0xAARRGGBB, so alpha << 24 will create a color with (alpha)% black.
            // Although the color components don't really matter, since the backing bitmap cache is
            // ALPHA_8.
            mTempPaint.setColor(sPatternLightness[i] << 24);
            canvas.drawPath(sPatternPaths[i], mTempPaint);
        }

        canvas.restore();
        mTempPaint.reset();
    }

    @VisibleForTesting
    public void scaleCanvasToBounds(Canvas canvas, Bitmap bitmap, Rect drawableBounds) {
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        float scaleX = drawableBounds.width() / (float) bitmapWidth;
        float scaleY = drawableBounds.height() / (float) bitmapHeight;

        // First scale both sides to fit independently.
        canvas.scale(scaleX, scaleY);
        if (scaleY > scaleX) {
            // Adjust x-scale to maintain aspect ratio using the pivot, so that more of the texture
            // and less of the blank space on the left edge is seen.
            canvas.scale(scaleY / scaleX, 1f, SCALE_FOCUS_X * bitmapWidth, 0f);
        } else if (scaleX > scaleY) {
            // Adjust y-scale to maintain aspect ratio using the pivot, so that an intersection of
            // two "circles" can always be seen.
            canvas.scale(1f, scaleX / scaleY, 0f, SCALE_FOCUS_Y * bitmapHeight);
        }
    }

    @Override
    public void setAlpha(int i) {
        // Ignore
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        // Ignore
    }

    @Override
    public int getOpacity() {
        return PixelFormat.UNKNOWN;
    }

    /**
     * Sets the color used as the base color of this pattern drawable. The alpha component of the
     * color will be ignored.
     */
    public void setColor(int color) {
        final int r = Color.red(color);
        final int g = Color.green(color);
        final int b = Color.blue(color);
        mColor = Color.argb(COLOR_ALPHA_INT, r, g, b);
        invalidateSelf();
    }

    /**
     * @return The color used as the base color of this pattern drawable. The alpha component of
     * this is always 255.
     */
    public int getColor() {
        return Color.argb(255, Color.red(mColor), Color.green(mColor), Color.blue(mColor));
    }
}
