package com.javacodegeeks.android.androidtimerexample;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.os.Handler;

import java.util.Random;

public class Periodic extends Activity 
{

	private Context mContext;
    private TextView mTv;
    private RelativeLayout mRl;
    private Random mRandom = new Random();
    private int mCounter;
    private int mMaxRepeat = 10;
    private Handler mHandler;
    private Runnable mRunnable;
    private int mInterval = 4000;
    private int mStartColor = Color.WHITE;
    private int mEndColor = 0;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.periodic);

        // Get the application context
        mContext = getApplicationContext();

        // Get the widgets reference from XML layout
        mRl = (RelativeLayout) findViewById(R.id.rl);
        Button btn = (Button) findViewById(R.id.btn);
        mTv = (TextView) findViewById(R.id.tv);

        // Set a background color for RelativeLayout
        mRl.setBackgroundColor(mStartColor);

        /*
            Handler
                A Handler allows you to send and process Message and Runnable objects associated
                with a thread's MessageQueue. Each Handler instance is associated with a single
                thread and that thread's message queue. When you create a new Handler, it is bound
                to the thread / message queue of the thread that is creating it -- from that point
                on, it will deliver messages and runnables to that message queue and execute them
                as they come out of the message queue.

            public Handler ()
                Default constructor associates this handler with the Looper for the current thread.
                If this thread does not have a looper, this handler won't be able to receive
                messages so an exception is thrown.


        */
		        // Initialize a new instance of Handler
		        mHandler = new Handler();

		        // Set a click listener for button
		        btn.setOnClickListener(new View.OnClickListener()
		        {
		        		@Override
		        		public void onClick(View view)
		        		{
		        			mCounter = 0;
			                /*
			                    Runnable
			                        Represents a command that can be executed. Often used to run code in a
			                        different Thread.
			
			                    Thread
			                        A Thread is a concurrent unit of execution. It has its own call stack for
			                        methods being invoked, their arguments and local variables. Each application
			                        has at least one thread running when it is started, the main thread, in the
			                        main ThreadGroup. The runtime keeps its own threads in the system thread group.
			
			                        There are two ways to execute code in a new thread. You can either subclass
			                        Thread and overriding its run() method, or construct a new Thread and pass a
			                        Runnable to the constructor. In either case, the start() method must be
			                        called to actually execute the new Thread.
			
			                */
		        			mRunnable = new Runnable()
		        			{
				                    /*
				                        public abstract void run ()
				                            Starts executing the active part of the class' code. This method is
				                            called when a thread is started that has been created with a class which
				                            implements Runnable.
				                    */
				                    @Override
				                    public void run() 
				                    {
				                        doTask();
				                    }
		        			};

			                /*
			                    public final boolean postDelayed (Runnable r, long delayMillis)
			                        Causes the Runnable r to be added to the message queue, to be run after the
			                        specified amount of time elapses. The runnable will be run on the thread to
			                        which this handler is attached. The time-base is uptimeMillis(). Time spent
			                        in deep sleep will add an additional delay to execution.
			                */
			                mHandler.postDelayed(mRunnable, (mInterval));
		        		}
		        });
    }

    protected void doTask()
    {
		        // Increase the counter by one
		        mCounter ++;
		
		        // If animation ending color is not assigned
		        if(mEndColor == 0)
		        {
		            // Assign a new color for animation end color
		            mEndColor = getRandomColor();
		        }
		
		        // Create an array of ColorDrawable
		        ColorDrawable[] colors = new ColorDrawable[]{
		                new ColorDrawable(mStartColor),
		                new ColorDrawable(mEndColor)
		        };
		
		        /*
		            We want to create a background color animation.
		            To play animation sequentially, we store the last animation ending color and
		            set it as the starting color of next color.
		        */
		        mStartColor = mEndColor;
		
		        // Animation ending color generate randomly, so it will be more attractive
		        mEndColor = getRandomColor();
		
		        // Initialize a new TransitionDrawable using ColorDrawable array
		        TransitionDrawable drawable = new TransitionDrawable(colors);
		
		        // Set the animation duration
		        drawable.startTransition(mInterval);
		
		        // Set the TransitionDrawable as RelativeLayout background drawable
		        mRl.setBackground(drawable);
		
		        // Display the number of times the task executed
		        mTv.setText("Task executed : " + mCounter + " times.");
		
		        // Schedule the task to do again after an interval
		        mHandler.postDelayed(mRunnable, mInterval);
		
		        // If the task reach the maximum repeat count then stop it here
		        if (mCounter == mMaxRepeat) 
		        {
		            /*
		                public final void removeCallbacks (Runnable r)
		                    Remove any pending posts of Runnable r that are in the message queue.
		            */
		            mHandler.removeCallbacks(mRunnable);
		        }
    }

    // Custom method to generate a random color
    protected int getRandomColor()
    {
	        // 256 is excluded, so random number between 0 to 255
	        int red = mRandom.nextInt(256);
	        int green = mRandom.nextInt(256);
	        int blue = mRandom.nextInt(256);
	        int color = Color.argb(255,red,green,blue);
	        return color;
    }
}