package com.linroid.sky31radio.view;

/**
 * Created by linroid on 1/14/15.
 */

import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.ProgressBar;

import com.linroid.sky31radio.R;
import com.linroid.sky31radio.utils.RadioUtils;

/**
 * This class handles the playpause button as well as the circular progress bar
 * it self-updates the progress bar but the containing activity/fragment
 * needs to add code to pause/resume this button to prevent unnecessary
 * updates while the activity/fragment is not visible
 */
public class PlayPauseProgressButton extends FrameLayout {
    private static final long UPDATE_FREQUENCY_MS = 500;
    private ProgressBar mProgressBar;
    private PlayPauseButton mPlayPauseButton;
    private Runnable mUpdateProgress;
    private boolean mPaused;

    public PlayPauseProgressButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        // set enabled to false as default so that calling enableAndShow will execute
        setEnabled(false);

        // set paused to false since we shouldn't be typically created while not visible
        mPaused = false;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        mPlayPauseButton = (PlayPauseButton)findViewById(R.id.action_button_play);
        mProgressBar = (ProgressBar)findViewById(R.id.circularProgressBar);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // Make the play pause button size dependent on the container size
        int horizontalPadding = getMeasuredWidth() / 4;
        int verticalPadding = getMeasuredHeight() / 4;
        mPlayPauseButton.setPadding(
                horizontalPadding, horizontalPadding,
                verticalPadding, verticalPadding);

        // rotate the progress bar 90 degrees counter clockwise so that the
        // starting position is at the top
        mProgressBar.setPivotX(mProgressBar.getMeasuredWidth() / 2);
        mProgressBar.setPivotY(mProgressBar.getMeasuredHeight() / 2);
        mProgressBar.setRotation(-90);
    }

    /**
     * Enable and shows the container
     */
    public void enableAndShow() {
        // enable
        setEnabled(true);

        // make our view visible
        setVisibility(VISIBLE);
    }

    /**
     * Disables and sets the visibility to gone for the container
     */
    public void disableAndHide() {
        // disable
        setEnabled(false);

        // hide our view
        setVisibility(GONE);
    }

    @Override
    public void setEnabled(boolean enabled) {
        // if the enabled state isn't changed, quit
        if (enabled == isEnabled()) return;

        super.setEnabled(enabled);

        // signal our state has changed
        onStateChanged();
    }

    /**
     * Pauses the progress bar periodic update logic
     */
    public void pause() {
        if (!mPaused) {
            mPaused = true;

            // signal our state has changed
            onStateChanged();
        }
    }

    /**
     * Resumes the progress bar periodic update logic
     */
    public void resume() {
        if (mPaused) {
            mPaused = false;

            // signal our state has changed
            onStateChanged();
        }
    }

    /**
     * @return play pause button
     */
    public PlayPauseButton getPlayPauseButton() {
        return mPlayPauseButton;
    }

    /**
     * Signaled if the state has changed (either the enabled or paused flag)
     * When the state changes, we either kick off the updates or remove them based on those flags
     */
    private void onStateChanged() {
        // if we are enabled and not paused
        if (isEnabled() && !mPaused) {
            // update the state of the progress bar and play/pause button
            updateState();

            // kick off update states
            postUpdate();
        } else {
            // otherwise remove our update
            removeUpdate();
        }
    }

    /**
     * Updates the state of the progress bar and the play pause button
     */
    private void updateState() {
        final long duration = RadioUtils.duration();

        if (duration > 0) {
            final long pos = RadioUtils.position();

            int progress = (int) (mProgressBar.getMax() * pos / duration);
            mProgressBar.setProgress(progress);
        } else {
            // this is when there are no tracks loaded or some kind of error condition
            mProgressBar.setProgress(0);
        }

        mPlayPauseButton.updateState();
    }

    /**
     * Creates and posts the update runnable to the handler
     */
    private void postUpdate() {
        if (mUpdateProgress == null) {
            mUpdateProgress = new Runnable() {
                @Override
                public void run() {
                    updateState();
                    postDelayed(mUpdateProgress, UPDATE_FREQUENCY_MS);
                }
            };
        }

        // remove any existing callbacks
        removeCallbacks(mUpdateProgress);

        // post ourselves as a delayed
        postDelayed(mUpdateProgress, UPDATE_FREQUENCY_MS);
    }

    /**
     * Removes the runnable from the handler
     */
    private void removeUpdate() {
        if (mUpdateProgress != null) {
            removeCallbacks(mUpdateProgress);
        }
    }
}

