/*
 * 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.fmradio.views;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;

/**
 * The view used to display the visualizer
 */
public final class FmVisualizerView extends View {

    private final Handler mHandler = new Handler();

    private Paint mPaint = new Paint();

    private float mColumnPadding = 3f;

    private boolean mAnimate = false;

    private int mFrequency = 100;

    private static final int COLUME_PADDING_COUNTS = 2;

    private static final int COLUME_COUNTS = 3;

    private static final float[] DEFALT_VISUALIZER_LEVEL = new float[] {
            +0.4f, 1f, -0.2f
    };

    private float[] mPrevLevels = DEFALT_VISUALIZER_LEVEL;

    /**
     * Constructor method
     *
     * @param context The context instance
     * @param attrs The attribute set for this view
     * @param defStyleAttr The default style for this view
     */
    public FmVisualizerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * Constructor method
     *
     * @param context The context instance
     * @param attrs The attribute set for this view
     */
    public FmVisualizerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * Constructor method
     *
     * @param context The context instance
     */
    public FmVisualizerView(Context context) {
        super(context);
        init();
    }

    private void init() {
        mPaint.setColor(0xff607d8b);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(0.3f);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mAnimate = false;
    }

    /**
     * Set the padding between visualizer columns
     *
     * @param padding The padding between visualizer columns
     */
    public void setColumnPadding(int padding) {
        mColumnPadding = padding;
    }

    /**
     * Start the animation
     */
    public void startAnimation() {
        mAnimate = true;
    }

    /**
     * Start the animation
     */
    public void stopAnimation() {
        mAnimate = false;
    }

    /**
     * Whether currently is under animation
     *
     * @return The animation state
     */
    public boolean isAnimated() {
        return mAnimate;
    }

    /**
     * Set the animation frequency
     *
     * @param freguency The specify animation frequency to set
     */
    public void setAnimateFrequency(int freguency) {
        mFrequency = freguency;
    }

    /**
     * Defined to re-freash the view
     */
    private final Runnable mRefreashRunnable = new Runnable() {
        public void run() {
            FmVisualizerView.this.invalidate();
        }
    };

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.drawColor(Color.TRANSPARENT);
        int viewHeight = getHeight();
        int viewWidth = getWidth();
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();
        float colWidth = ((float) (viewWidth - paddingLeft - paddingRight - COLUME_PADDING_COUNTS
                * mColumnPadding))
                / COLUME_COUNTS;
        float colHeight = (float) (viewHeight - paddingBottom - paddingTop);

        float levels[] = new float[COLUME_COUNTS];
        if (!mAnimate) {
            levels = DEFALT_VISUALIZER_LEVEL;
        } else {
            levels = generate(COLUME_COUNTS);
        }
        for (int i = 0; i < COLUME_COUNTS; i++) {
            float left = paddingLeft + i * (mColumnPadding + colWidth);
            float right = left + colWidth;
            float startY = paddingTop + colHeight / 2;
            startY -= colHeight / 2 * levels[i];
            if (startY < paddingTop) {
                startY = paddingTop;
            }
            float bottom = viewHeight - paddingBottom;
            RectF rect = new RectF(left, startY, right, bottom);
            canvas.drawRect(rect, mPaint);
        }
        mHandler.removeCallbacks(mRefreashRunnable);
        mHandler.postDelayed(mRefreashRunnable, mFrequency);
    }

    /**
     * Used to generate out the float array with specify array count
     *
     * @param count The array count
     * @return A float array with specify array count
     */
    private float[] generate(int count) {
        if (count <= 0) {
            return null;
        }
        int[] sign = {
                -1, 1
        };
        float[] result = new float[count];
        for (int i = 0; i < count; i++) {
            while (true) {
                result[i] = (float) Math.random() * 1f
                        * (float) sign[(int) (Math.random() * 2)];
                if (Math.abs(mPrevLevels[i] - result[i]) < 0.3f & result[i] > -0.3f) {
                    break;
                }
            }
        }
        mPrevLevels = result;
        return result;
    }
}
