/*
 * 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.content.res.ColorStateList;
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.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.DrawableWrapper;
import android.os.Handler;
import android.telephony.CellSignalStrength;
import android.util.LayoutDirection;
import android.util.PathParser;

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

/**
 * Drawable displaying a mobile cell signal indicator.
 */
public class SignalDrawable extends DrawableWrapper {

    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 DOT_SIZE = 3f / VIEWPORT;
    private static final float DOT_PADDING = 1.5f / VIEWPORT;

    // 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_CUT = 2;
    private static final int STATE_CARRIER_CHANGE = 3;

    private static final long DOT_DELAY = 1000;

    private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mTransparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final int mDarkModeFillColor;
    private final int mLightModeFillColor;
    private final Path mCutoutPath = new Path();
    private final Path mForegroundPath = new Path();
    private final Path mXPath = new Path();
    private final Matrix mXScaleMatrix = new Matrix();
    private final Path mScaledXPath = new Path();
    private final Handler mHandler;
    private final float mCutoutWidthFraction;
    private final float mCutoutHeightFraction;
    private float mDarkIntensity = -1;
    private final int mIntrinsicSize;
    private boolean mAnimating;
    private int mCurrentDot;

    public SignalDrawable(Context context) {
        super(context.getDrawable(com.android.internal.R.drawable.ic_signal_cellular));
        final String xPathString = context.getString(
                com.android.internal.R.string.config_signalXPath);
        mXPath.set(PathParser.createPathFromPathData(xPathString));
        updateScaledXPath();
        mCutoutWidthFraction = context.getResources().getFloat(
                com.android.internal.R.dimen.config_signalCutoutWidthFraction);
        mCutoutHeightFraction = context.getResources().getFloat(
                com.android.internal.R.dimen.config_signalCutoutHeightFraction);
        mDarkModeFillColor = Utils.getColorStateListDefaultColor(context,
                R.color.dark_mode_icon_color_single_tone);
        mLightModeFillColor = Utils.getColorStateListDefaultColor(context,
                R.color.light_mode_icon_color_single_tone);
        mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
        mTransparentPaint.setColor(context.getColor(android.R.color.transparent));
        mTransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        mHandler = new Handler();
        setDarkIntensity(0);
    }

    private void updateScaledXPath() {
        if (getBounds().isEmpty()) {
            mXScaleMatrix.setScale(1f, 1f);
        } else {
            mXScaleMatrix.setScale(getBounds().width() / VIEWPORT, getBounds().height() / VIEWPORT);
        }
        mXPath.transform(mXScaleMatrix, mScaledXPath);
    }

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

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

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

    @Override
    protected boolean onLevelChange(int packedState) {
        super.onLevelChange(unpackLevel(packedState));
        updateAnimation();
        setTintList(ColorStateList.valueOf(mForegroundPaint.getColor()));
        invalidateSelf();
        return true;
    }

    private int unpackLevel(int packedState) {
        int numBins = (packedState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
        int levelOffset = numBins == (CellSignalStrength.getNumSignalStrengthLevels() + 1) ? 10 : 0;
        int level = (packedState & LEVEL_MASK);
        return level + levelOffset;
    }

    public void setDarkIntensity(float darkIntensity) {
        if (darkIntensity == mDarkIntensity) {
            return;
        }
        setTintList(ColorStateList.valueOf(getFillColor(darkIntensity)));
    }

    @Override
    public void setTintList(ColorStateList tint) {
        super.setTintList(tint);
        int colorForeground = mForegroundPaint.getColor();
        mForegroundPaint.setColor(tint.getDefaultColor());
        if (colorForeground != mForegroundPaint.getColor()) invalidateSelf();
    }

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

    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);
        updateScaledXPath();
        invalidateSelf();
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.saveLayer(null, null);
        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);
        }
        super.draw(canvas);
        mCutoutPath.reset();
        mCutoutPath.setFillType(FillType.WINDING);

        final float padding = Math.round(PAD * width);

        if (isInState(STATE_CARRIER_CHANGE)) {
            float dotSize = (DOT_SIZE * height);
            float dotPadding = (DOT_PADDING * height);
            float dotSpacing = dotPadding + dotSize;
            float x = width - padding - dotSize;
            float y = height - padding - dotSize;
            mForegroundPath.reset();
            drawDotAndPadding(x, y, dotPadding, dotSize, 2);
            drawDotAndPadding(x - dotSpacing, y, dotPadding, dotSize, 1);
            drawDotAndPadding(x - dotSpacing * 2, y, dotPadding, dotSize, 0);
            canvas.drawPath(mCutoutPath, mTransparentPaint);
            canvas.drawPath(mForegroundPath, mForegroundPaint);
        } else if (isInState(STATE_CUT)) {
            float cutX = (mCutoutWidthFraction * width / VIEWPORT);
            float cutY = (mCutoutHeightFraction * height / VIEWPORT);
            mCutoutPath.moveTo(width, height);
            mCutoutPath.rLineTo(-cutX, 0);
            mCutoutPath.rLineTo(0, -cutY);
            mCutoutPath.rLineTo(cutX, 0);
            mCutoutPath.rLineTo(0, cutY);
            canvas.drawPath(mCutoutPath, mTransparentPaint);
            canvas.drawPath(mScaledXPath, mForegroundPaint);
        }
        if (isRtl) {
            canvas.restore();
        }
        canvas.restore();
    }

    private void drawDotAndPadding(float x, float y,
            float dotPadding, float dotSize, int i) {
        if (i == mCurrentDot) {
            // Draw dot
            mForegroundPath.addRect(x, y, x + dotSize, y + dotSize, Direction.CW);
            // Draw dot padding
            mCutoutPath.addRect(x - dotPadding, y - dotPadding, x + dotSize + dotPadding,
                    y + dotSize + dotPadding, Direction.CW);
        }
    }

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

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

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

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

    /**
     * Returns whether this drawable is in the specified state.
     *
     * @param state must be one of {@link #STATE_CARRIER_CHANGE} or {@link #STATE_CUT}
     */
    private boolean isInState(int state) {
        return getState(getLevel()) == state;
    }

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

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

    /** Returns the state representing empty mobile signal with the given number of levels. */
    public static int getEmptyState(int numLevels) {
        return getState(0, numLevels, true);
    }

    /** Returns the state representing carrier change with the given number of levels. */
    public static int getCarrierChangeState(int numLevels) {
        return (STATE_CARRIER_CHANGE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
    }
}
