/*
 * Copyright (C) 2017 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.settingslib.graph;

import android.animation.ArgbEvaluator;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;
import android.graphics.Path.Op;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.LayoutDirection;

import com.android.settingslib.R;
import com.android.settingslib.Utils;

public class SignalDrawable extends Drawable {

    private static final String TAG = "SignalDrawable";

    private static final int NUM_DOTS = 3;

    private static final float VIEWPORT = 24f;
    private static final float PAD = 2f / VIEWPORT;
    private static final float CUT_OUT = 7.9f / VIEWPORT;

    private static final float DOT_SIZE = 3f / VIEWPORT;
    private static final float DOT_PADDING = 1f / VIEWPORT;
    private static final float DOT_CUT_WIDTH = (DOT_SIZE * 3) + (DOT_PADDING * 5);
    private static final float DOT_CUT_HEIGHT = (DOT_SIZE * 1) + (DOT_PADDING * 1);

    private static final float[] FIT = {2.26f, -3.02f, 1.76f};

    // All of these are masks to push all of the drawable state into one int for easy callbacks
    // and flow through sysui.
    private static final int LEVEL_MASK = 0xff;
    private static final int NUM_LEVEL_SHIFT = 8;
    private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT;
    private static final int STATE_SHIFT = 16;
    private static final int STATE_MASK = 0xff << STATE_SHIFT;
    private static final int STATE_NONE = 0;
    private static final int STATE_EMPTY = 1;
    private static final int STATE_CUT = 2;
    private static final int STATE_CARRIER_CHANGE = 3;
    private static final int STATE_AIRPLANE = 4;

    private static final long DOT_DELAY = 1000;

    private static float[][] X_PATH = new float[][]{
            {21.9f / VIEWPORT, 17.0f / VIEWPORT},
            {-1.1f / VIEWPORT, -1.1f / VIEWPORT},
            {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
            {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
            {-1.1f / VIEWPORT, 1.1f / VIEWPORT},
            {1.9f / VIEWPORT, 1.9f / VIEWPORT},
            {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
            {1.1f / VIEWPORT, 1.1f / VIEWPORT},
            {1.9f / VIEWPORT, -1.9f / VIEWPORT},
            {1.9f / VIEWPORT, 1.9f / VIEWPORT},
            {1.1f / VIEWPORT, -1.1f / VIEWPORT},
            {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
    };

    // Rounded corners are achieved by arcing a circle of radius `R` from its tangent points along
    // the curve (curve ≡ triangle). On the top and left corners of the triangle, the tangents are
    // as follows:
    //      1) Along the straight lines (y = 0 and x = width):
    //          Ps = circleOffset + R
    //      2) Along the diagonal line (y = x):
    //          Pd = √((Ps^2) / 2)
    //              or (remember: sin(π/4) ≈ 0.7071)
    //          Pd = (circleOffset + R - 0.7071, height - R - 0.7071)
    //         Where Pd is the (x,y) coords of the point that intersects the circle at the bottom
    //         left of the triangle
    private static final float RADIUS_RATIO = 0.75f / 17f;
    private static final float DIAG_OFFSET_MULTIPLIER = 0.707107f;
    // How far the circle defining the corners is inset from the edges
    private final float mAppliedCornerInset;

    private static final float INV_TAN = 1f / (float) Math.tan(Math.PI / 8f);
    private static final float CUT_WIDTH_DP = 1f / 12f;

    // Where the top and left points of the triangle would be if not for rounding
    private final PointF mVirtualTop  = new PointF();
    private final PointF mVirtualLeft = new PointF();

    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final int mDarkModeBackgroundColor;
    private final int mDarkModeFillColor;
    private final int mLightModeBackgroundColor;
    private final int mLightModeFillColor;
    private final Path mFullPath = new Path();
    private final Path mForegroundPath = new Path();
    private final Path mXPath = new Path();
    // Cut out when STATE_EMPTY
    private final Path mCutPath = new Path();
    // Draws the slash when in airplane mode
    private final SlashArtist mSlash = new SlashArtist();
    private final Handler mHandler;
    private float mOldDarkIntensity = -1;
    private float mNumLevels = 1;
    private int mIntrinsicSize;
    private int mLevel;
    private int mState;
    private boolean mVisible;
    private boolean mAnimating;
    private int mCurrentDot;

    public SignalDrawable(Context context) {
        mDarkModeBackgroundColor =
                Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_background);
        mDarkModeFillColor =
                Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_fill);
        mLightModeBackgroundColor =
                Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_background);
        mLightModeFillColor =
                Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill);
        mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);

        mHandler = new Handler();
        setDarkIntensity(0);

        mAppliedCornerInset = context.getResources()
                .getDimensionPixelSize(R.dimen.stat_sys_mobile_signal_circle_inset);
    }

    public void setIntrinsicSize(int size) {
        mIntrinsicSize = size;
    }

    @Override
    public int getIntrinsicWidth() {
        return mIntrinsicSize;
    }

    @Override
    public int getIntrinsicHeight() {
        return mIntrinsicSize;
    }

    public void setNumLevels(int levels) {
        if (levels == mNumLevels) return;
        mNumLevels = levels;
        invalidateSelf();
    }

    private void setSignalState(int state) {
        if (state == mState) return;
        mState = state;
        updateAnimation();
        invalidateSelf();
    }

    private void updateAnimation() {
        boolean shouldAnimate = (mState == STATE_CARRIER_CHANGE) && mVisible;
        if (shouldAnimate == mAnimating) return;
        mAnimating = shouldAnimate;
        if (shouldAnimate) {
            mChangeDot.run();
        } else {
            mHandler.removeCallbacks(mChangeDot);
        }
    }

    @Override
    protected boolean onLevelChange(int state) {
        setNumLevels(getNumLevels(state));
        setSignalState(getState(state));
        int level = getLevel(state);
        if (level != mLevel) {
            mLevel = level;
            invalidateSelf();
        }
        return true;
    }

    public void setColors(int background, int foreground) {
        mPaint.setColor(background);
        mForegroundPaint.setColor(foreground);
    }

    public void setDarkIntensity(float darkIntensity) {
        if (darkIntensity == mOldDarkIntensity) {
            return;
        }
        mPaint.setColor(getBackgroundColor(darkIntensity));
        mForegroundPaint.setColor(getFillColor(darkIntensity));
        mOldDarkIntensity = darkIntensity;
        invalidateSelf();
    }

    private int getFillColor(float darkIntensity) {
        return getColorForDarkIntensity(
                darkIntensity, mLightModeFillColor, mDarkModeFillColor);
    }

    private int getBackgroundColor(float darkIntensity) {
        return getColorForDarkIntensity(
                darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
    }

    private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
        return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        invalidateSelf();
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        final float width = getBounds().width();
        final float height = getBounds().height();

        boolean isRtl = getLayoutDirection() == LayoutDirection.RTL;
        if (isRtl) {
            canvas.save();
            // Mirror the drawable
            canvas.translate(width, 0);
            canvas.scale(-1.0f, 1.0f);
        }
        mFullPath.reset();
        mFullPath.setFillType(FillType.WINDING);

        final float padding = Math.round(PAD * width);
        final float cornerRadius = RADIUS_RATIO * height;
        // Offset from circle where the hypotenuse meets the circle
        final float diagOffset = DIAG_OFFSET_MULTIPLIER * cornerRadius;

        // 1 - Bottom right, above corner
        mFullPath.moveTo(width - padding, height - padding - cornerRadius);
        // 2 - Line to top right, below corner
        mFullPath.lineTo(width - padding, padding + cornerRadius + mAppliedCornerInset);
        // 3 - Arc to top right, on hypotenuse
        mFullPath.arcTo(
                width - padding - (2 * cornerRadius),
                padding + mAppliedCornerInset,
                width - padding,
                padding + mAppliedCornerInset + (2 * cornerRadius),
                0.f, -135.f, false
        );
        // 4 - Line to bottom left, on hypotenuse
        mFullPath.lineTo(padding + mAppliedCornerInset + cornerRadius - diagOffset,
                height - padding - cornerRadius - diagOffset);
        // 5 - Arc to bottom left, on leg
        mFullPath.arcTo(
                padding + mAppliedCornerInset,
                height - padding - (2 * cornerRadius),
                padding + mAppliedCornerInset + ( 2 * cornerRadius),
                height - padding,
                -135.f, -135.f, false
        );
        // 6 - Line to bottom rght, before corner
        mFullPath.lineTo(width - padding - cornerRadius, height - padding);
        // 7 - Arc to beginning (bottom right, above corner)
        mFullPath.arcTo(
                width - padding - (2 * cornerRadius),
                height - padding - (2 * cornerRadius),
                width - padding,
                height - padding,
                90.f, -90.f, false
        );

        if (mState == STATE_CARRIER_CHANGE) {
            float cutWidth = (DOT_CUT_WIDTH * width);
            float cutHeight = (DOT_CUT_HEIGHT * width);
            float dotSize = (DOT_SIZE * height);
            float dotPadding = (DOT_PADDING * height);

            mFullPath.moveTo(width - padding, height - padding);
            mFullPath.rLineTo(-cutWidth, 0);
            mFullPath.rLineTo(0, -cutHeight);
            mFullPath.rLineTo(cutWidth, 0);
            mFullPath.rLineTo(0, cutHeight);
            float dotSpacing = dotPadding * 2 + dotSize;
            float x = width - padding - dotSize;
            float y = height - padding - dotSize;
            mForegroundPath.reset();
            drawDot(mFullPath, mForegroundPath, x, y, dotSize, 2);
            drawDot(mFullPath, mForegroundPath, x - dotSpacing, y, dotSize, 1);
            drawDot(mFullPath, mForegroundPath, x - dotSpacing * 2, y, dotSize, 0);
        } else if (mState == STATE_CUT) {
            float cut = (CUT_OUT * width);
            mFullPath.moveTo(width - padding, height - padding);
            mFullPath.rLineTo(-cut, 0);
            mFullPath.rLineTo(0, -cut);
            mFullPath.rLineTo(cut, 0);
            mFullPath.rLineTo(0, cut);
        }

        if (mState == STATE_EMPTY) {
            // Where the corners would be if this were a real triangle
            mVirtualTop.set(
                    width - padding,
                    (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius));
            mVirtualLeft.set(
                    (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius),
                    height - padding);

            final float cutWidth = CUT_WIDTH_DP * height;
            final float cutDiagInset = cutWidth * INV_TAN;

            // Cut out a smaller triangle from the center of mFullPath
            mCutPath.reset();
            mCutPath.setFillType(FillType.WINDING);
            mCutPath.moveTo(width - padding - cutWidth, height - padding - cutWidth);
            mCutPath.lineTo(width - padding - cutWidth, mVirtualTop.y + cutDiagInset);
            mCutPath.lineTo(mVirtualLeft.x + cutDiagInset, height - padding - cutWidth);
            mCutPath.lineTo(width - padding - cutWidth, height - padding - cutWidth);

            // Draw empty state as only background
            mForegroundPath.reset();
            mFullPath.op(mCutPath, Path.Op.DIFFERENCE);
        } else if (mState == STATE_AIRPLANE) {
            // Airplane mode is slashed, fully drawn background
            mForegroundPath.reset();
            mSlash.draw((int) height, (int) width, canvas, mPaint);
        } else if (mState != STATE_CARRIER_CHANGE) {
            mForegroundPath.reset();
            int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding));
            mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding,
                    Direction.CW);
            mForegroundPath.op(mFullPath, Op.INTERSECT);
        }

        canvas.drawPath(mFullPath, mPaint);
        canvas.drawPath(mForegroundPath, mForegroundPaint);
        if (mState == STATE_CUT) {
            mXPath.reset();
            mXPath.moveTo(X_PATH[0][0] * width, X_PATH[0][1] * height);
            for (int i = 1; i < X_PATH.length; i++) {
                mXPath.rLineTo(X_PATH[i][0] * width, X_PATH[i][1] * height);
            }
            canvas.drawPath(mXPath, mForegroundPaint);
        }
        if (isRtl) {
            canvas.restore();
        }
    }

    private void drawDot(Path fullPath, Path foregroundPath, float x, float y, float dotSize,
            int i) {
        Path p = (i == mCurrentDot) ? foregroundPath : fullPath;
        p.addRect(x, y, x + dotSize, y + dotSize, Direction.CW);
    }

    // This is a fit line based on previous values of provided in assets, but if
    // you look at the a plot of this actual fit, it makes a lot of sense, what it does
    // is compress the areas that are very visually easy to see changes (the middle sections)
    // and spread out the sections that are hard to see (each end of the icon).
    // The current fit is cubic, but pretty easy to change the way the code is written (just add
    // terms to the end of FIT).
    private float calcFit(float v) {
        float ret = 0;
        float t = v;
        for (int i = 0; i < FIT.length; i++) {
            ret += FIT[i] * t;
            t *= v;
        }
        return ret;
    }

    @Override
    public int getAlpha() {
        return mPaint.getAlpha();
    }

    @Override
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
        mPaint.setAlpha(alpha);
        mForegroundPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        mForegroundPaint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return 255;
    }

    @Override
    public boolean setVisible(boolean visible, boolean restart) {
        mVisible = visible;
        updateAnimation();
        return super.setVisible(visible, restart);
    }

    private final Runnable mChangeDot = new Runnable() {
        @Override
        public void run() {
            if (++mCurrentDot == NUM_DOTS) {
                mCurrentDot = 0;
            }
            invalidateSelf();
            mHandler.postDelayed(mChangeDot, DOT_DELAY);
        }
    };

    public static int getLevel(int fullState) {
        return fullState & LEVEL_MASK;
    }

    public static int getState(int fullState) {
        return (fullState & STATE_MASK) >> STATE_SHIFT;
    }

    public static int getNumLevels(int fullState) {
        return (fullState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
    }

    public static int getState(int level, int numLevels, boolean cutOut) {
        return ((cutOut ? STATE_CUT : 0) << STATE_SHIFT)
                | (numLevels << NUM_LEVEL_SHIFT)
                | level;
    }

    public static int getCarrierChangeState(int numLevels) {
        return (STATE_CARRIER_CHANGE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
    }

    public static int getEmptyState(int numLevels) {
        return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
    }

    public static int getAirplaneModeState(int numLevels) {
        return (STATE_AIRPLANE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
    }

    private final class SlashArtist {
        private static final float CORNER_RADIUS = 1f;
        // These values are derived in un-rotated (vertical) orientation
        private static final float SLASH_WIDTH = 1.8384776f;
        private static final float SLASH_HEIGHT = 22f;
        private static final float CENTER_X = 10.65f;
        private static final float CENTER_Y = 15.869239f;
        private static final float SCALE = 24f;

        // Bottom is derived during animation
        private static final float LEFT = (CENTER_X - (SLASH_WIDTH / 2)) / SCALE;
        private static final float TOP = (CENTER_Y - (SLASH_HEIGHT / 2)) / SCALE;
        private static final float RIGHT = (CENTER_X + (SLASH_WIDTH / 2)) / SCALE;
        private static final float BOTTOM = (CENTER_Y + (SLASH_HEIGHT / 2)) / SCALE;
        // Draw the slash washington-monument style; rotate to no-u-turn style
        private static final float ROTATION = -45f;

        private final Path mPath = new Path();
        private final RectF mSlashRect = new RectF();

        void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
            Matrix m = new Matrix();
            final float radius = scale(CORNER_RADIUS, width);
            updateRect(
                    scale(LEFT, width),
                    scale(TOP, height),
                    scale(RIGHT, width),
                    scale(BOTTOM, height));

            mPath.reset();
            // Draw the slash vertically
            mPath.addRoundRect(mSlashRect, radius, radius, Direction.CW);
            m.setRotate(ROTATION, width / 2, height / 2);
            mPath.transform(m);
            canvas.drawPath(mPath, paint);

            // Rotate back to vertical, and draw the cut-out rect next to this one
            m.setRotate(-ROTATION, width / 2, height / 2);
            mPath.transform(m);
            m.setTranslate(mSlashRect.width(), 0);
            mPath.transform(m);
            mPath.addRoundRect(mSlashRect, radius, radius, Direction.CW);
            m.setRotate(ROTATION, width / 2, height / 2);
            mPath.transform(m);
            canvas.clipOutPath(mPath);
        }

        void updateRect(float left, float top, float right, float bottom) {
            mSlashRect.left = left;
            mSlashRect.top = top;
            mSlashRect.right = right;
            mSlashRect.bottom = bottom;
        }

        private float scale(float frac, int width) {
            return frac * width;
        }
    }
}
