/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.queplix.core.client.app;

import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.DialogBox;
import com.queplix.core.client.app.rpc.RPC;
import com.queplix.core.client.common.ui.DialogAnswerListener;
import com.queplix.core.client.common.ui.DialogHelper;
import com.queplix.core.client.common.ui.WindowHelper;

/**
 * User session manager.
 *
 * @author Sultan Tezadov
 * @since 1 Mar 2007
 */
public abstract class UserSessionManager {
    private static Timer timer;
    private static Timer dialogTimer;
    private static int warningAfterMillis;
    private static int warningForMinutes;

    /**
     * Initialization.
     *
     * @param sessionTimeoutMinutes user session timeout value
     * @param sessionTimeoutWarnBeforeMinutes
     *                              the number of minutes before
     *                              session times out a warning dialog will be displayed
     */
    public static void init(int sessionTimeoutMinutes,
                            int sessionTimeoutWarnBeforeMinutes) {
        if(sessionTimeoutMinutes <= 0) {
            return;
        }
        if(sessionTimeoutWarnBeforeMinutes <= 0) {
            return;
        }
        int warningAfterMinutes = sessionTimeoutMinutes
                - sessionTimeoutWarnBeforeMinutes
                - 1; // 1 minute reserved for inaccuracy
        if(warningAfterMinutes <= 0) {
            return;
        }

        timer = new Timer() {
            public void run() {
                showWarning();
            }
        };
        warningAfterMillis = warningAfterMinutes * 60000;
        warningForMinutes = sessionTimeoutWarnBeforeMinutes;
        resetTimer();
    }

    /**
     * Reset timer for session expiration warning display.
     */
    public static void resetTimer() {
        if(timer != null) {
            timer.schedule(warningAfterMillis);
        }
    }

    private static void showWarning() {
        String question =
                "You session will timeout in " + warningForMinutes +
                        " minutes. Press OK to stay connected or Log Off to " +
                        "terminate your session.";
        int answerSet = DialogHelper.OK + DialogHelper.LOG_OFF;
        DialogAnswerListener listener = new DialogAnswerListener() {
            public void anserIs(int answer) {
                dialogTimer.cancel();
                processChoice(answer == DialogHelper.LOG_OFF);
            }
        };
        final DialogBox dialog =
                DialogHelper.showQuestionDialog(question, answerSet, listener);
        if(dialogTimer == null) {
            dialogTimer = new Timer() {
                public void run() {
                    processNoChoice(dialog);
                }
            };
        }
        int warningForMillis = warningForMinutes * 60000;
        dialogTimer.schedule(warningForMillis);
    }

    private static void processChoice(boolean logout) {
        if(logout) {
            logout();
        } else {
            keepSessionAlive();
        }
    }

    private static void processNoChoice(DialogBox dialog) {
        // the user has not made any choice
        dialog.hide();
        processChoice(true); // logout
    }

    /**
     * Log out from the application without confirmations.
     */
    public static void logout() {
        RPC.QAsyncCallback callback = new RPC.QAsyncCallback() {
            public void onRequestEnded(boolean success, Object result) {
                if(success) {
                    WindowHelper.navigate("Logout.html");
                }
            }
        };
        RPC.getRPC().logout(callback);
    }

    /**
     * Make a keep alive call to refresh session timeout counter.
     */
    public static void keepSessionAlive() {
        RPC.QAsyncCallback callback = new RPC.QAsyncCallback() {
            public void onRequestEnded(boolean success, Object result) {
            }
        };
        RPC.getRPC().keepSessionAlive(callback);
    }
}
