/*
 * Copyright (C) 2013 Reece H. Dunn
 *
 * 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.reecedunn.espeak.preference;

import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;

import com.reecedunn.espeak.R;

public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener
{
    private SeekBar mSeekBar;
    private TextView mValueText;

    private int mOldProgress = 0;
    private int mProgress = 0;
    private int mDefaultValue = 0;
    private int mMin = 0;
    private int mMax = 100;
    private String mFormatter = "%s";

    public void setProgress(int progress) {
        mProgress = progress;
        String text = Integer.toString(mProgress);
        callChangeListener(text);

        // Update the last saved value to the so it can be restored later if
        // the user cancels the dialog. This needs to be done here as well
        // as the onProgressChanged handler as the SeekBar will not be
        // initialized at this point.

        mOldProgress = mProgress;
    }

    public int getProgress() {
        return mProgress;
    }

    public void setDefaultValue(int defaultValue) {
        mDefaultValue = defaultValue;
    }

    public int getDefaultValue() {
        return mDefaultValue;
    }

    public void setMin(int min) {
        mMin =  min;
    }

    public int getMin() {
        return mMin;
    }

    public void setMax(int max) {
        mMax =  max;
    }

    public int getMax() {
        return mMax;
    }

    public void setFormatter(String formatter) {
        mFormatter = formatter;
    }

    public String getFormatter() {
        return mFormatter;
    }

    public SeekBarPreference(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        setDialogLayoutResource(R.layout.seekbar_preference);
        setLayoutResource(R.layout.information_view);
        setPositiveButtonText(android.R.string.ok);
        setNegativeButtonText(android.R.string.cancel);
    }

    public SeekBarPreference(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public SeekBarPreference(Context context)
    {
        this(context, null);
    }

    private void persistSettings(int progress) {
        mProgress = progress;
        String text = Integer.toString(mProgress);
        callChangeListener(text);
        if (shouldCommit()) {
            SharedPreferences.Editor editor = getEditor();
            editor.putString(getKey(), text);
            editor.commit();
        }
    }

    @Override
    protected View onCreateDialogView() {
        View root = super.onCreateDialogView();
        mSeekBar = (SeekBar)root.findViewById(R.id.seekBar);
        mValueText = (TextView)root.findViewById(R.id.valueText);

        Button reset = (Button)root.findViewById(R.id.resetToDefault);
        reset.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v)
            {
                int defaultValue = getDefaultValue();
                mSeekBar.setProgress(defaultValue - mMin);

                // Persist the value here to ensure that eSpeak is using the
                // new value the next time e.g. TalkBack reads part of the UI.

                persistSettings(defaultValue);
            }
        });
        return root;
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
        mSeekBar.setOnSeekBarChangeListener(this);
        mSeekBar.setMax(mMax - mMin);
        mSeekBar.setProgress(mProgress - mMin);

        // Update the last saved value to the so it can be restored later if
        // the user cancels the dialog.

        mOldProgress = mProgress;
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                // Update the last saved value so this will be persisted when
                // the dialog is dismissed.

                mOldProgress = mSeekBar.getProgress() + mMin;
                break;
        }
        super.onClick(dialog, which);
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        // There are 3 ways to dismiss a dialog:
        //   1.  Pressing the OK (positive) button.
        //   2.  Pressing the Cancel (negative) button.
        //   3.  Pressing the Back button.
        //
        // For [1], the new value needs to be persisted. For [2] and [3], the
        // old value needs to be persisted (so the last saved value is
        // restored). As there is no easy way to override the Dialog's back
        // button pressed handler, the following approach is used:
        //
        // 1.  If the user presses the OK button, the last saved value is
        //     updated to be the new value (see the onClick handler).
        //
        // 2.  In all cases, the last saved value is persisted when the dialog
        //     is closed (in this onDismiss handler).

        persistSettings(mOldProgress);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
    {
        // This callback gets called frequently when the user is moving the
        // slider, so constantly persisting the seeker value will be annoying.
        //
        // If the value is being set programatically, persisting the seeker
        // value here will cause the speech rate to be set to 80 WPM (via the
        // onBindDialogView handler).

        String text = String.format(getFormatter(), Integer.toString(progress + mMin));
        mValueText.setText(text);
        mSeekBar.setContentDescription(text);
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar)
    {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar)
    {
        // After the user has let go of the slider, the new value is
        // persisted to ensure that eSpeak is using the new value the
        // next time e.g. TalkBack reads part of the UI.

        persistSettings(mSeekBar.getProgress() + mMin);
    }
}
