/*******************************************************************************
* Copyright (c) 2013 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.tabris.internal;
import static com.eclipsesource.tabris.internal.Clauses.when;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class SwipeItemIndexer implements Serializable {
private int currentIndex;
private int range;
private int oldIndex;
private boolean dirty;
public SwipeItemIndexer() {
range = 1;
reset();
}
public void reset() {
currentIndex = -1;
oldIndex = -1;
}
public void setRange( int range ) {
when( range <= 0 ).throwIllegalArgument( "Range must be > 0 but was " + range );
this.range = range;
}
public int getRange() {
return range;
}
public void setCurrent( int index ) {
dirty = true;
when( index < 0 ).throwIllegalArgument( "Index must be positive but was " + index );
oldIndex = currentIndex;
currentIndex = index;
}
public int getOld() {
return oldIndex;
}
public int getCurrent() {
return currentIndex;
}
public int[] getPrevious() {
int[] result = getEmptyRange();
if( range > 0 ) {
int[] newRange = getRange( currentIndex );
result = computePreviousIndexes( newRange );
}
return result;
}
private int[] computePreviousIndexes( int[] newRange ) {
int[] result = new int[ range ];
if( currentIndex > 0 || oldIndex > 0) {
if( currentIndex >= oldIndex || isAJump() ) {
result = computeFollowUps( newRange );
} else {
result = computeInvertedFollowUps( newRange );
}
} else {
result = getEmptyRange();
}
return result;
}
public int[] getNext() {
int[] result = getEmptyRange();
if( range > 0 ) {
int[] newRange = getRange( currentIndex );
result = computeNextIndexes( newRange );
}
return result;
}
private int[] getRange( int index ) {
List<Integer> rangeItems = new ArrayList<Integer>();
for( int i = ( index - range ); i <= ( index + range ); i++ ) {
if( i >= 0 ) {
rangeItems.add( Integer.valueOf( i ) );
}
}
return getAsArray( rangeItems );
}
private int[] computeNextIndexes( int[] newRange ) {
int[] result = new int[ range + 1 ];
if( currentIndex > oldIndex || isAJump() ) {
result = computeInvertedFollowUps( newRange );
} else {
if( currentIndex > 0 ) {
result = computeFollowUps( newRange );
} else {
result = getEmptyRange();
}
}
return result;
}
private boolean isAJump() {
return ( currentIndex - oldIndex ) > 1 || ( oldIndex - currentIndex ) > 1;
}
private int[] computeInvertedFollowUps( int[] indexes ) {
List<Integer> result = new ArrayList<Integer>();
for( int i = 0; i < indexes.length; i++ ) {
if( indexes[ i ] > currentIndex ) {
result.add( Integer.valueOf( indexes[ i ] ) );
}
}
return getAsArray( result );
}
private int[] computeFollowUps( int[] indexes ) {
List<Integer> result = new ArrayList<Integer>();
for( int i = 0; i < indexes.length; i++ ) {
if( indexes[ i ] < currentIndex ) {
result.add( Integer.valueOf( indexes[ i ] ) );
}
}
return getAsArray( result );
}
public int[] popOutOfRangeIndexes() {
int[] result = getEmptyRange();
if( dirty && oldIndex != -1 ) {
result = computeOutOfRangeIndexes();
dirty = false;
}
return result;
}
private int[] getEmptyRange() {
return new int[] {};
}
private int[] computeOutOfRangeIndexes() {
int[] newRange = getRange( currentIndex );
int[] oldRange = getRange( oldIndex );
return computeDelta( oldRange, newRange );
}
private int[] computeDelta( int[] oldRange, int[] newRange ) {
List<Integer> delta = new ArrayList<Integer>();
List<Integer> oldIndexes = getAsList( oldRange );
List<Integer> newIndexes = getAsList( newRange );
for( Integer index : oldIndexes ) {
if( !newIndexes.contains( index ) ) {
delta.add( index );
}
}
return getAsArray( delta );
}
public static List<Integer> getAsList( int[] indexes ) {
ArrayList<Integer> result = new ArrayList<Integer>();
for( int index : indexes ) {
result.add( Integer.valueOf( index ) );
}
return result;
}
public static int[] getAsArray( List<Integer> indexes ) {
int result[] = new int[ indexes.size() ];
for( int i = 0; i < indexes.size(); i++ ) {
Integer index = indexes.get( i );
result[ i ] = index.intValue();
}
return result;
}
}