/*
 * Copyright (c) 2008-2015 Haulmont. All rights reserved.
 * Use is subject to license terms, see http://www.cuba-platform.com/license for details.
 */

package com.haulmont.cuba.web.toolkit.ui.client.historycontrol;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.History;
import com.haulmont.cuba.web.toolkit.ui.client.logging.ClientLogger;
import com.haulmont.cuba.web.toolkit.ui.client.logging.ClientLoggerFactory;
import com.vaadin.client.BrowserInfo;

/**
 * @author gorelov
 * @version $Id$
 */
public abstract class HistoryGwtApi {
    protected ClientLogger logger = ClientLoggerFactory.getLogger("HistoryGwtApi");
    private static String TOP_HISTORY_TOKEN = "!";
    private static String PREVIOUS_HISTORY_TOKEN = "_";
    private String previousHistoryToken;
    private boolean isForward;
    private HandlerRegistration handlerRegistration;
    private boolean isFireHistoryState;

    public HistoryGwtApi() {
        logger.log(">>> INIT <<<");
        initStartState();
        initHandler();
    }

    protected void initStartState() {
        isForward = false;
        isFireHistoryState = false;
        previousHistoryToken = TOP_HISTORY_TOKEN;
        // we need to add new history tokens BEFORE ValueChangeHandler will added
        if (urlHasToken(TOP_HISTORY_TOKEN)) {
            History.newItem(PREVIOUS_HISTORY_TOKEN);
            // if init url has TOP_HISTORY_TOKEN, we inform what PREVIOUS_HISTORY_TOKEN should be fired,
            // otherwise not all state variables will have proper values
            isFireHistoryState = true;
        } else {
            History.newItem(TOP_HISTORY_TOKEN);
        }
    }

    protected void initHandler() {
        handlerRegistration = History.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                String historyToken = event.getValue();
                if (isForward) {
                    isForward = false;
                    // here we assume that "forward" action was performed
                    // and if current history token equals to TOP_HISTORY_TOKEN
                    // then this is true, otherwise we ignore
                    if (TOP_HISTORY_TOKEN.equals(historyToken)) {
                        handleHistoryStep();
                    }
                } else {
                    if (!TOP_HISTORY_TOKEN.equals(historyToken)) {
                        // if current history token equals to previous history token
                        // then we assume that "back" action was performed
                        if (previousHistoryToken.equals(historyToken)) {
                            isForward = true;
                        } else {
                            // otherwise we assume that some handmade token was processed
                            // and replace it with PREVIOUS_HISTORY_TOKEN
                            previousHistoryToken = historyToken;
                            History.newItem(PREVIOUS_HISTORY_TOKEN);
                        }
                    }
                    // we always must have TOP_HISTORY_TOKEN on top of history stack
                    // if it is, then History will ignore the call of newItem method.
                    History.newItem(TOP_HISTORY_TOKEN);
                }
            }
        });
        if (isFireHistoryState)
            History.fireCurrentHistoryState();
    }

    protected boolean urlHasToken(String token) {
        String url = Document.get().getURL();
        logger.log("url = " + url);
        return url.contains("#" + token);
    }

    protected abstract void onHistoryBackPerformed();

    protected abstract boolean isEnabled();

    public void disable() {
        logger.log(">>> DISABLE <<<");
        handlerRegistration.removeHandler();
    }

    protected void handleHistoryStep() {
        if (!isEnabled()) {
            logger.log(">>> Disabled history handler");
            disable();
            return;
        }

        if (!BrowserInfo.get().isIE()) {
            goForward();
        } else {
            goForwardDelayed();
        }
    }

    protected void goForward() {
        logger.log(">>> Call history back handler");
        onHistoryBackPerformed();
    }

    protected void goForwardDelayed() {
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                goForward();
            }
        });
    }
}
@@ -817,93 +817,8 @@
  %7B%0D%0A
-    protected ClientLogger logger = ClientLoggerFactory.getLogger(%22HistoryGwtApi%22);%0D%0A
     
@@ -828,24 +828,30 @@
 vate static 
+final 
 String TOP_H
@@ -890,16 +890,22 @@
  static 
+final 
 String P
@@ -938,80 +938,95 @@
 %22;%0D%0A
+%0D%0A
     pr
-ivate String previousHistoryToken;%0D%0A    private boolean isForward;
+otected ClientLogger logger = ClientLoggerFactory.getLogger(%22HistoryGwtApi%22);%0D%0A
 %0D%0A  
@@ -1073,24 +1073,126 @@
 istration;%0D%0A
+    private String previousHistoryToken = TOP_HISTORY_TOKEN;%0D%0A    private boolean isForward = false;%0D%0A
     private 
@@ -1217,16 +1217,24 @@
 oryState
+ = false
 ;%0D%0A%0D%0A   
@@ -1400,124 +1400,8 @@
  %7B%0D%0A
-        isForward = false;%0D%0A        isFireHistoryState = false;%0D%0A        previousHistoryToken = TOP_HISTORY_TOKEN;%0D%0A
     

Rewrite HistoryControl using GWT History API #PL-4702