package com.vaguehope.onosendai.ui;

import android.content.Context;
import android.graphics.Color;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

public class ScrollIndicator {

	private static final int ITEM_HEIGHT_DIP = 2;
	private static final int BAR_WIDTH_DIP = 7;
	private static final int COLOUR = Color.GRAY;

	private ScrollIndicator () {
		throw new AssertionError();
	}

	public static void attach (final Context context, final ViewGroup rootView, final ListView tweetList) {
		final AbsoluteShape bar = new AbsoluteShape(context);
		bar.layoutForce(0, 0, 0, 0);
		bar.setBackgroundColor(COLOUR);
		bar.bringToFront();
		rootView.addView(bar);

		final int barWidth = (int) dipToPixels(context, BAR_WIDTH_DIP);
		final float pxPerItem = dipToPixels(context, ITEM_HEIGHT_DIP);

		tweetList.setOnScrollListener(new BarMovingScrollListener(bar, pxPerItem, barWidth));
	}

	private static float dipToPixels (final Context context, final int a) {
		return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, a, context.getResources().getDisplayMetrics());
	}

	private static class AbsoluteShape extends View {

		public AbsoluteShape (final Context context) {
			super(context);
		}

		@Override
		public void layout (final int l, final int t, final int r, final int b) {
			/* block calls so no layout manager can not mess with us. */
		}

		public void layoutForce (final int l, final int t, final int r, final int b) {
			super.layout(l, t, r, b);
		}

	}

	private static class BarMovingScrollListener implements OnScrollListener {

		private final AbsoluteShape bar;
		private final float pxPerItem;
		private final int barWidth;

		private int lastPosition = -1;

		public BarMovingScrollListener (final AbsoluteShape bar, final float pxPerItem, final int barWidth) {
			this.bar = bar;
			this.pxPerItem = pxPerItem;
			this.barWidth = barWidth;
		}

		@Override
		public void onScrollStateChanged (final AbsListView view, final int scrollStateFlag) {
			final int position = view.getFirstVisiblePosition();
			if (position != this.lastPosition) {
				final int y = (int) (position * this.pxPerItem);
				this.bar.layoutForce(view.getRight() - this.barWidth, view.getTop(), view.getRight(), view.getTop() + y);
				this.lastPosition = position;
			}
		}

		@Override
		public void onScroll (final AbsListView view, final int firstVisibleItem, final int visibleItemCount, final int totalItemCount) {
			onScrollStateChanged(view, 0);
		}

	}

}

@@ -364,27 +364,115 @@
 int 
-ITEM_HEIGHT_DIP = 2
+ACCEL_STOP_1 = 5;%0A%09private static final int ACCEL_STOP_2 = 15;%0A%09private static final int ACCEL_STOP_3 = 100
 ;%0A%09p
@@ -912,28 +912,25 @@
 nal 
-int barWidth = (int)
+float pxPerUnit =
  dip
@@ -951,49 +951,86 @@
 xt, 
-BAR_WIDTH_DIP);%0A%09%09final float pxPerItem =
+1); // Perhaps this should be a %25 of list height?%0A%09%09final int barWidth = (int)
  dip
@@ -1051,19 +1051,17 @@
 xt, 
-ITEM_HEIGHT
+BAR_WIDTH
 _DIP
@@ -1134,20 +1134,20 @@
 r, pxPer
-Item
+Unit
 , barWid
@@ -1881,28 +1881,28 @@
  float pxPer
-Item
+Unit
 ;%0A%09%09private 
@@ -2032,20 +2032,20 @@
 at pxPer
-Item
+Unit
 , final 
@@ -2096,20 +2096,20 @@
 xPer
-Item
+Unit
  = pxPer
 Item
@@ -2104,20 +2104,20 @@
  = pxPer
-Item
+Unit
 ;%0A%09%09%09thi
@@ -2355,17 +2355,17 @@
 nal int 
-y
+h
  = (int)
@@ -2365,16 +2365,17 @@
 = (int) 
+(
 (positio
@@ -2375,16 +2375,140 @@
 position
+%0A%09%09%09%09%09%09+ Math.min(position, ACCEL_STOP_1)%0A%09%09%09%09%09%09+ Math.min(position, ACCEL_STOP_2)%0A%09%09%09%09%09%09+ Math.min(position, ACCEL_STOP_3))
  * this.
@@ -2512,20 +2512,20 @@
 is.pxPer
-Item
+Unit
 );%0A%09%09%09%09t
@@ -2625,17 +2625,17 @@
 Top() + 
-y
+h
 );%0A%09%09%09%09t

Make ScrollIndicator height slightly non-linear.