package com.github.jjobes.slidedaytimepicker;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.format.DateFormat;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
import android.widget.TimePicker;

/**
 * The fragment for the second page in the ViewPager that holds
 * the {@link CustomTimePicker}.
 *
 * @author jjobes
 *
 */
public class TimeFragment extends Fragment
{
    /**
     * Used to communicate back to the parent fragment as the user
     * is changing the time spinners so we can dynamically update
     * the tab text.
     */
    public interface TimeChangedListener
    {
        void onTimeChanged(int hour, int minute);
    }

    private TimeChangedListener mCallback;
    private TimePicker mTimePicker;

    public TimeFragment()
    {
        // Required empty public constructor for fragment.
    }

    /**
     * Cast the reference to {@link SlideDayTimeDialogFragment} to a
     * {@link TimeChangedListener}.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        try
        {
            mCallback = (TimeChangedListener) getTargetFragment();
        }
        catch (ClassCastException e)
        {
            throw new ClassCastException("Calling fragment must implement " +
                "TimeFragment.TimeChangedListener interface");
        }
    }

    /**
     * Return an instance of TimeFragment with its bundle filled with the
     * constructor arguments. The values in the bundle are retrieved in
     * {@link #onCreateView()} below to properly initialize the TimePicker.
     *
     * @param theme
     * @param hour
     * @param minute
     * @param isClientSpecified24HourTime
     * @param is24HourTime
     * @return
     */
    public static final TimeFragment newInstance(int theme, int hour, int minute,
        boolean isClientSpecified24HourTime, boolean is24HourTime)
    {
        TimeFragment f = new TimeFragment();

        Bundle b = new Bundle();
        b.putInt("theme", theme);
        b.putInt("hour", hour);
        b.putInt("minute", minute);
        b.putBoolean("isClientSpecified24HourTime", isClientSpecified24HourTime);
        b.putBoolean("is24HourTime", is24HourTime);
        f.setArguments(b);

        return f;
    }

    /**
     * Create and return the user interface view for this fragment.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        int theme = getArguments().getInt("theme");
        int initialHour = getArguments().getInt("hour");
        int initialMinute = getArguments().getInt("minute");
        boolean isClientSpecified24HourTime = getArguments().getBoolean("isClientSpecified24HourTime");
        boolean is24HourTime = getArguments().getBoolean("is24HourTime");

        // Unless we inflate using a cloned inflater with a Holo theme,
        // on Lollipop devices the TimePicker will be the new-style
        // radial TimePicker, which is not what we want. So we will
        // clone the inflater that we're given but with our specified
        // theme, then inflate the layout with this new inflater.

        Context contextThemeWrapper = new ContextThemeWrapper(
                getActivity(),
                theme == SlideDayTimePicker.HOLO_DARK ?
                        android.R.style.Theme_Holo : android.R.style.Theme_Holo_Light);
        LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
        View v = localInflater.inflate(R.layout.fragment_time, container, false);

        mTimePicker = (TimePicker) v.findViewById(R.id.timePicker);
        // block keyboard popping up on touch
        mTimePicker.setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
        mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute)
            {
                mCallback.onTimeChanged(hourOfDay, minute);
            }
        });

        // If the client specifies a 24-hour time format, set it on
        // the TimePicker.
        if (isClientSpecified24HourTime)
        {
            mTimePicker.setIs24HourView(is24HourTime);
        }
        else
        {
            // If the client does not specify a 24-hour time format, use the
            // device default.
            mTimePicker.setIs24HourView(DateFormat.is24HourFormat(
                getTargetFragment().getActivity()));
        }

        mTimePicker.setCurrentHour(initialHour);
        mTimePicker.setCurrentMinute(initialMinute);

        // Fix for the bug where a TimePicker's onTimeChanged() is not called when
        // the user toggles the AM/PM button. Only applies to 4.0.0 and 4.0.3.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
            Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
        {
            fixTimePickerBug18982();
        }

        return v;
    }

    /**
     * Workaround for bug in Android TimePicker where the onTimeChanged() callback
     * is not invoked when the user toggles between AM/PM. But we need to be able
     * to detect this in order to dynamically update the tab title properly when
     * the user toggles between AM/PM.
     *
     * Registered as Issue 18982:
     *
     * https://code.google.com/p/android/issues/detail?id=18982
     */
    private void fixTimePickerBug18982()
    {
        View amPmView = ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(3);

        if (amPmView instanceof NumberPicker)
        {
            ((NumberPicker) amPmView).setOnValueChangedListener(new OnValueChangeListener() {

                @Override
                public void onValueChange(NumberPicker picker, int oldVal, int newVal)
                {
                    if (picker.getValue() == 1)  // PM
                    {
                        if (mTimePicker.getCurrentHour() < 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() + 12);
                    }
                    else  // AM
                    {
                        if (mTimePicker.getCurrentHour() >= 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() - 12);
                    }

                    mCallback.onTimeChanged(
                        mTimePicker.getCurrentHour(),
                        mTimePicker.getCurrentMinute());
                }
            });
        }
    }
}