/*
 * Copyright (C) 2011 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.settings;

import static android.view.HapticFeedbackConstants.CLOCK_TICK;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;

public class PointerSpeedPreference extends SeekBarDialogPreference implements
        SeekBar.OnSeekBarChangeListener {
    private final InputManager mIm;
    private SeekBar mSeekBar;

    private int mOldSpeed;
    private boolean mRestoredOldState;

    private boolean mTouchInProgress;
    private int mLastProgress = -1;

    private ContentObserver mSpeedObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            onSpeedChanged();
        }
    };

    public PointerSpeedPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        mIm = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
    }

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

        getContext().getContentResolver().registerContentObserver(
                Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
                mSpeedObserver);

        mRestoredOldState = false;
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);

        mSeekBar = getSeekBar(view);
        mSeekBar.setMax(InputManager.MAX_POINTER_SPEED - InputManager.MIN_POINTER_SPEED);
        mOldSpeed = mIm.getPointerSpeed(getContext());
        mSeekBar.setProgress(mOldSpeed - InputManager.MIN_POINTER_SPEED);
        mSeekBar.setOnSeekBarChangeListener(this);
        mSeekBar.setContentDescription(getTitle());
    }

    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
        if (!mTouchInProgress) {
            mIm.tryPointerSpeed(progress + InputManager.MIN_POINTER_SPEED);
        }
        if (progress != mLastProgress) {
            seekBar.performHapticFeedback(CLOCK_TICK);
            mLastProgress = progress;
        }
    }

    public void onStartTrackingTouch(SeekBar seekBar) {
        mTouchInProgress = true;
    }

    public void onStopTrackingTouch(SeekBar seekBar) {
        mTouchInProgress = false;
        mIm.tryPointerSpeed(seekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
    }

    private void onSpeedChanged() {
        int speed = mIm.getPointerSpeed(getContext());
        mSeekBar.setProgress(speed - InputManager.MIN_POINTER_SPEED);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        final ContentResolver resolver = getContext().getContentResolver();

        if (positiveResult) {
            mIm.setPointerSpeed(getContext(),
                    mSeekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
        } else {
            restoreOldState();
        }

        resolver.unregisterContentObserver(mSpeedObserver);
    }

    private void restoreOldState() {
        if (mRestoredOldState) return;

        mIm.tryPointerSpeed(mOldSpeed);
        mRestoredOldState = true;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        final Parcelable superState = super.onSaveInstanceState();
        if (getDialog() == null || !getDialog().isShowing()) return superState;

        // Save the dialog state
        final SavedState myState = new SavedState(superState);
        myState.progress = mSeekBar.getProgress();
        myState.oldSpeed = mOldSpeed;

        // Restore the old state when the activity or dialog is being paused
        restoreOldState();
        return myState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state == null || !state.getClass().equals(SavedState.class)) {
            // Didn't save state for us in onSaveInstanceState
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState myState = (SavedState) state;
        super.onRestoreInstanceState(myState.getSuperState());
        mOldSpeed = myState.oldSpeed;
        mIm.tryPointerSpeed(myState.progress + InputManager.MIN_POINTER_SPEED);
    }

    private static class SavedState extends BaseSavedState {
        int progress;
        int oldSpeed;

        public SavedState(Parcel source) {
            super(source);
            progress = source.readInt();
            oldSpeed = source.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(progress);
            dest.writeInt(oldSpeed);
        }

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {

            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
}

