package org.apache.struts.util;

import java.util.Collection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;

public class Pager {

        protected int offset = 0;

        protected int pageSize = 10;

        protected int totalSize = -1;

        protected boolean useCash = false;

        protected boolean hideCurrent = true;

        protected Collection container = null;

        protected PagerEntry[] cash = null;

        protected String pageSizeParameterName = "pageSize";

        protected String offsetParameterName = "offset";

        public Pager() {}

        public Pager( Collection container ) {
                setContainer( container );
        }

        public boolean getHideCurrent() {
                return hideCurrent;
        }

        public void setHideCurrent( boolean hideCurrent ) {
                this.hideCurrent = hideCurrent;
        }

        public boolean getUseCash() {
                return useCash;
        }

        public void setUseCash( boolean useCash ) {
                this.useCash = useCash;
        }

        public void setContainer( Collection container ) {
                this.container = container;
        }

        public Collection getContainer() {
                return container;
        }

        public int getOffset() {
                return offset;
        }

        public void setOffset( int offset ) {
                if( offset < 0 ) offset = 0;
                this.offset = offset;
        }

        public int getPageSize() {
                return pageSize;
        }

        public void setPageSize( int pageSize ) {
                if( pageSize <= 0 ) pageSize = 10;
                this.pageSize = pageSize;
        }

        public int getTotalSize() {
                return totalSize;
        }

        public void setTotalSize( int totalSize ) {
                this.totalSize = totalSize;
        }

        public int getSize() {
                if( totalSize < 0 )  {
                        if( container==null ) {
                                return 0;
                        } else {
                                return container.size();
                        }
                } else {
                        return totalSize;
                }
        }

        public int getPagesTotal() {
                int size = getSize();
                int pageSize = getPageSize();
                int pages = size / pageSize;
                if( ( size % pageSize ) > 0 ) pages++;
                return pages;
        }

        public int pageNumber( int forOffset ) {
                return forOffset / getPageSize();
        }

        public PagerEntry linkTo( int pageNumber ) {
                HashMap link = new HashMap();
                boolean isCurrent = ( ( getCurrentPageNumber() == pageNumber ) ? true : false );
                link.put( offsetParameterName, Integer.toString( pageNumber * getPageSize() ) );
                link.put( pageSizeParameterName, Integer.toString( getPageSize() ) );
                return new PagerEntry( label( pageNumber ), link, isCurrent );
        }

        public String label( int pageNumber ) {
                return Integer.toString( pageNumber + 1 );
        }

        public int getCurrentPageNumber() {
                return pageNumber( getOffset() );
        }

        public boolean getHasPrev() {
                return getCurrentPageNumber() > 0;
        }

        public boolean getHasNext() {
                return getCurrentPageNumber() < getPagesTotal() - 1;
        }

        public PagerEntry getPrev() {
                if( getHasPrev() ) {
                        if( useCash ) {
                                if( cash == null )
                                        fillCash();
                                return cash[ getCurrentPageNumber() - 1 ];
                        } else {
                                return linkTo( getCurrentPageNumber() - 1 );
                        }
                }
                return null;
        }

        public PagerEntry getNext() {
                if( getHasNext() ) {
                        if( useCash ) {
                                if( cash == null )
                                        fillCash();
                                return cash[ getCurrentPageNumber() + 1 ];
                        } else
                                return linkTo( getCurrentPageNumber() + 1 );
                }
                return null;
        }
        
        public void fillCash() {
                int pagesTotal = getPagesTotal();
                cash = new PagerEntry[ pagesTotal ];
                for( int i = 0; i < pagesTotal ; i++ ) {
                        cash[ i ] = linkTo( i );
                }                
        }

        public Iterator getIterator() {
                if( useCash ) {
                        if( cash == null )
                                fillCash();
                        return Arrays.asList( cash ).iterator();
                } else {
                        return new PagerIterator( this );
                }
        }

}

