/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.richfaces.renderkit.html;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.PhaseId;

import org.ajax4jsf.Messages;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.ajax4jsf.renderkit.HeaderResourcesRendererBase;
import org.richfaces.component.UIDatascroller;
import org.richfaces.event.DataScrollerEvent;


public class DataScrollerRenderer extends HeaderResourcesRendererBase {

    protected Class getComponentClass() {
        return UIDatascroller.class;
    }
    
    protected boolean isRenderedOnSinglePage(UIDatascroller scroller, UIData dataTable) {
        return (scroller.getPageCount(dataTable) != 1 || scroller.isRenderIfSinglePage());
    }

    public void doDecode(FacesContext context, UIComponent component) {

        UIDatascroller scroller = (UIDatascroller) component;

        if (isRenderedOnSinglePage(scroller, scroller.getDataTable())) {
            String param = (String) getParamMap(context).get(
                    component.getClientId(context));
            if (param != null) {
                DataScrollerEvent event = new DataScrollerEvent(scroller,
                        String.valueOf(scroller.getPageIndex()), param);
                if (scroller.isImmediate()) {
                    event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
                } else {
                    event.setPhaseId(PhaseId.INVOKE_APPLICATION);
                }

                component.queueEvent(event);
            }
        }
    }

    public ControlsState getControlsState(FacesContext context,
            UIDatascroller datascroller, UIData dataTable) {
        int pageIndex = datascroller.getPageIndex(dataTable);
        int pageCount = datascroller.getPageCount(dataTable);
        int minPageIdx = 1;
        int maxPageIdx = pageCount;
        int fastStep = datascroller.getFastStep();
        if (fastStep <= 1) {
            fastStep = 1;
        }

        boolean useFirst = true;
        boolean useLast = true;

        boolean useBackFast = true;
        boolean useForwFast = true;

        ControlsState controlsState = new ControlsState();

        if (pageIndex <= minPageIdx) {
            useFirst = false;
        }

        if (pageIndex >= maxPageIdx) {
            useLast = false;
        }

        if (pageIndex - fastStep < minPageIdx) {
            useBackFast = false;
        }

        if (pageIndex + fastStep > maxPageIdx) {
            useForwFast = false;
        }

        boolean isAuto;
        String boundaryControls = datascroller.getBoundaryControls();
        String stepControls = datascroller.getStepControls();
        String fastControls = datascroller.getFastControls();

        if ((isAuto = "auto".equals(boundaryControls)) || "show".equals(
                boundaryControls)) {
            if (isAuto) {
                controlsState.setFirstRendered(useFirst);
                controlsState.setLastRendered(useLast);
            }

            controlsState.setFirstEnabled(useFirst);
            controlsState.setLastEnabled(useLast);
        } else {
            controlsState.setFirstRendered(false);
            controlsState.setLastRendered(false);
        }

        if ((isAuto = "auto".equals(stepControls)) || "show".equals(
                stepControls)) {
            if (isAuto) {
                controlsState.setPreviousRendered(useFirst);
                controlsState.setNextRendered(useLast);
            }

            controlsState.setPreviousEnabled(useFirst);
            controlsState.setNextEnabled(useLast);
        } else {
            controlsState.setPreviousRendered(false);
            controlsState.setNextRendered(false);
        }

        if ((isAuto = "auto".equals(fastControls)) || "show".equals(
                fastControls)) {
            if (isAuto) {
                controlsState.setFastForwardRendered(useForwFast);
                controlsState.setFastRewindRendered(useBackFast);
            }

            controlsState.setFastForwardEnabled(useForwFast);
            controlsState.setFastRewindEnabled(useBackFast);
        } else {
            controlsState.setFastForwardRendered(false);
            controlsState.setFastRewindRendered(false);
        }

        UIComponent controlsSeparatorFacet = datascroller.getFacet("controlsSeparator");
        if (controlsSeparatorFacet != null && controlsSeparatorFacet.isRendered()) {
        	controlsState.setControlsSeparatorRendered(true);
        }
        
        return controlsState;
    }

    public void renderPager(FacesContext context, UIComponent component, UIData data)
            throws IOException {
        ResponseWriter out = context.getResponseWriter();
        UIDatascroller scroller = (UIDatascroller) component;
        int currentPage = scroller.getPageIndex(data);

        int maxPages = scroller.getMaxPages();
        if (maxPages <= 1) {
            maxPages = 1;
        }
        int pageCount = scroller.getPageCount(data);
        if (pageCount <= 1) {
            return;
        }

        int delta = maxPages / 2;

        int pages;
        int start;
        if (pageCount > maxPages && currentPage > delta) {
            pages = maxPages;
            start = currentPage - pages / 2 - 1;
            if (start + pages > pageCount) {
                start = pageCount - pages;
            }
        } else {
            pages = pageCount < maxPages ? pageCount : maxPages;
            start = 0;
        }

        for (int i = start, size = start + pages; i < size; i++) {

            boolean isCurrentPage = (i + 1 == currentPage);
            String styleClass;
            String style;
			if (isCurrentPage) {
			    styleClass = scroller.getSelectedStyleClass();
			    style = scroller.getSelectedStyle();
			} else {
				styleClass = scroller.getInactiveStyleClass();
			    style = scroller.getInactiveStyle();
			}
			if (styleClass==null){
			    styleClass="";
			}

            out.startElement("td", component);
            
            if (isCurrentPage) {
                out.writeAttribute("class", "dr-dscr-act rich-datascr-act "+
                		styleClass, null);
            } else {
                out.writeAttribute("class", "dr-dscr-inact rich-datascr-inact "+
                		styleClass, null);
                out.writeAttribute("onclick", getOnClick(context, component,
                        Integer.toString(i + 1)), null);
            }
            if (null != style) out.writeAttribute("style", style, null);
            out.writeText(Integer.toString(i + 1), null);
            //renderChild(context, link);
            out.endElement("td");
        }

    }

    public void renderPages(FacesContext context, UIComponent component, UIData data)
            throws IOException {
        UIDatascroller scroller = (UIDatascroller) component;
        int currentPage = scroller.getPageIndex(data);

        int pageCount = scroller.getPageCount(data);
        if (pageCount <= 1) {
            pageCount = 1;
        }
        String varName = (String) scroller.getAttributes().get("pageIndexVar");
        if (varName != null && varName.length() > 0) {
            context.getExternalContext()
                    .getRequestMap().put(varName, new Integer(currentPage));
        }
        varName = (String) scroller.getAttributes().get("pagesVar");
        if (varName != null && varName.length() > 0) {
            context.getExternalContext()
                    .getRequestMap().put(varName, new Integer(pageCount));
        }
    }

    private Map getParamMap(FacesContext context) {
        return context.getExternalContext().getRequestParameterMap();
    }

    //get UIParameter's Map
    protected Map getParameters(FacesContext context, UIComponent component){
    	Map parameters = new HashMap(); 
    	
    	if(component instanceof UIDatascroller){
    		UIDatascroller datascroller = (UIDatascroller)component;
    		List children = datascroller.getChildren();
    		for (Iterator iterator = children.iterator(); iterator.hasNext();) {
				UIComponent child = (UIComponent) iterator.next();
				if(child instanceof UIParameter) {
					UIParameter param = (UIParameter)child;
					String name = param.getName();
					if (name != null) {
						parameters.put(name, param.getValue());
					}
				}
			}
    	}
    	    	
    	return parameters;
    }
    
    public String getOnClick(FacesContext context, UIComponent component,
            String value) {

        JSFunction function = AjaxRendererUtils.buildAjaxFunction(component,
                context);
        UIDatascroller scroller = (UIDatascroller) component;
        Map eventOptions = AjaxRendererUtils.buildEventOptions(context,
                component);
        Map parameters = (Map) eventOptions.get("parameters");
        parameters.put(scroller.getClientId(context), value);
        
        Map params = getParameters(context,component);
        if(!params.isEmpty()){
        	parameters.putAll(params);
        }
        
        function.addParameter(eventOptions);
        StringBuffer buffer = new StringBuffer();
        function.appendScript(buffer);
        buffer.append("; return false;");
        String script = buffer.toString();
        return script;
    }


    /** Creates HtmlAjaxCommandLink sets its id, value and reRender and UIParameter */
    public boolean getRendersChildren() {
        return true;
    }
}
