/*
 * The MIT License
 *
 * Copyright 2012 Masahiko, SAWAI <masahiko.sawai@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.example.hello.android.view_composite_hello;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;

/**
 *
 * @author Masahiko, SAWAI <masahiko.sawai@gmail.com>
 */
public class NumberPicker extends LinearLayout implements
	View.OnClickListener, TextWatcher
{

	// Model
	private float minValue;
	private float maxValue;
	private float value;
	private float increment;
	// Views
	private EditText numberEditText;
	private ImageButton upImageButton;
	private ImageButton downImageButton;

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

	public NumberPicker(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		setOrientation(VERTICAL);

		numberEditText = new EditText(context);
		upImageButton = new ImageButton(context);
		downImageButton = new ImageButton(context);

		TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumberPicker);
		minValue = ta.getFloat(R.styleable.NumberPicker_minValue, 0);
		maxValue = ta.getFloat(R.styleable.NumberPicker_maxValue, 100);
		value = ta.getFloat(R.styleable.NumberPicker_value, 50);
		increment = ta.getFloat(R.styleable.NumberPicker_increment, 1);

		float textSize = ta.getDimension(R.styleable.NumberPicker_android_textSize, numberEditText.getTextSize());
		ColorStateList colorStateList = ta.getColorStateList(R.styleable.NumberPicker_android_textColor);

		// check range
		if (maxValue < minValue)
		{
			maxValue = minValue;
		}

		if (value < minValue)
		{
			value = minValue;
		}
		else if (value > maxValue)
		{
			value = maxValue;
		}

		Log.d("XXX", "NumberPicker() : maxValue => " + maxValue);
		Log.d("XXX", "NumberPicker() : minValue => " + minValue);
		Log.d("XXX", "NumberPicker() : value => " + value);
		Log.d("XXX", "NumberPicker() : increment => " + increment);
		Log.d("XXX", "NumberPicker() : textSize => " + textSize);
		Log.d("XXX", "NumberPicker() : colorStateList => " + colorStateList);

		numberEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
		numberEditText.setText(String.valueOf(value));
		numberEditText.setGravity(Gravity.RIGHT);
		numberEditText.addTextChangedListener(this);
		numberEditText.setTextSize(textSize);
		if (colorStateList != null)
		{
			numberEditText.setTextColor(colorStateList);
		}

		upImageButton.setImageResource(R.drawable.ic_arrow_up_light);
		upImageButton.setOnClickListener(this);

		downImageButton.setImageResource(R.drawable.ic_arrow_down_light);
		downImageButton.setOnClickListener(this);

		addView(upImageButton, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		addView(numberEditText, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		addView(downImageButton, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
	}

	public float getMaxValue()
	{
		return maxValue;
	}

	public void setMaxValue(float maxValue)
	{
		this.maxValue = maxValue;
	}

	public float getMinValue()
	{
		return minValue;
	}

	public void setMinValue(float minValue)
	{
		this.minValue = minValue;
	}

	public float getValue()
	{
		return value;
	}

	public void setValue(float newValue)
	{
		if (newValue < minValue)
		{
			newValue = minValue;
		}
		if (newValue > maxValue)
		{
			newValue = maxValue;
		}
		this.value = newValue;
	}

	public float getIncrement()
	{
		return increment;
	}

	public void setIncrement(float increment)
	{
		this.increment = increment;
	}

	public void onClick(View v)
	{
		Log.v("XXX", "onClick() : Hello");

		float newValue = value;
		if (v == upImageButton)
		{
			newValue += increment;
		}
		else if (v == downImageButton)
		{
			newValue -= increment;
		}

		setValue(newValue);
		numberEditText.setText(String.valueOf(value));

		Log.v("XXX", "onClick() : Bye");
	}

	public void beforeTextChanged(CharSequence s, int start, int count, int after)
	{
		Log.v("XXX", "beforeTextChanged() : Hello");
	}

	public void onTextChanged(CharSequence s, int start, int before, int count)
	{
		Log.v("XXX", "onTextChanged() : Hello");
	}

	public void afterTextChanged(Editable s)
	{
		Log.v("XXX", "afterTextChanged() : Hello");
		try
		{
			float newValue = Float.parseFloat(s.toString());
			setValue(newValue);
		}
		catch (NumberFormatException e)
		{
		}
		Log.v("XXX", "afterTextChanged() : Bye");
	}

	/**
	 * Save instance state
	 *
	 * id が付いている場合しか呼ばれないので注意
	 *
	 * @return 状態を保存した Parcelable オブジェクト
	 */
	@Override
	protected Parcelable onSaveInstanceState()
	{
		Log.v("XXX", "onSaveInstanceState() : Hello");

		Parcelable parent = super.onSaveInstanceState();
		NumberPickerSavedState savedState = new NumberPickerSavedState(parent);
		savedState.value = this.value;
		savedState.maxValue = this.maxValue;
		savedState.minValue = this.minValue;
		savedState.increment = this.increment;

		Log.v("XXX", "onSaveInstanceState() : Bye");
		return savedState;
	}

	@Override
	protected void onRestoreInstanceState(Parcelable state)
	{
		Log.v("XXX", "onRestoreInstanceState() : Hello");

		if (state instanceof NumberPickerSavedState)
		{
			NumberPickerSavedState savedState = (NumberPickerSavedState) state;

			super.onRestoreInstanceState(savedState.getSuperState());

			setMaxValue(savedState.maxValue);
			setMinValue(savedState.minValue);
			setIncrement(savedState.increment);
			setValue(savedState.value);
			numberEditText.setText(String.valueOf(value));
		}

		Log.v("XXX", "onRestoreInstanceState() : Bye");
	}

	static class NumberPickerSavedState extends View.BaseSavedState
	{

		float minValue;
		float maxValue;
		float value;
		float increment;

		public NumberPickerSavedState(Parcel source)
		{
			super(source);
			minValue = source.readFloat();
			maxValue = source.readFloat();
			value = source.readFloat();
			increment = source.readFloat();
		}

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

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

			dest.writeFloat(minValue);
			dest.writeFloat(maxValue);
			dest.writeFloat(value);
			dest.writeFloat(increment);
		}
		public static final Parcelable.Creator CREATOR = new Parcelable.Creator<NumberPickerSavedState>()
		{
			public NumberPickerSavedState createFromParcel(Parcel source)
			{
				return new NumberPickerSavedState(source);
			}

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