/*
 * 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.integrator;

import com.queplix.core.client.app.rpc.RPCException;
import com.queplix.core.client.app.vo.LoginRequestObject;
import com.queplix.core.client.app.vo.LoginResult;
import com.queplix.core.client.app.vo.MetaData;
import com.queplix.core.integrator.security.BadNameOrPasswordException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.integrator.security.WebLoginManager;
import com.queplix.core.integrator.util.CustomPropertiesLoader;
import com.queplix.core.modules.statistics.UserLog;
import com.queplix.core.utils.SystemHelper;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;
import com.queplix.core.utils.www.GWTHelper;
import com.queplix.core.utils.www.WarClassLoaderHelper;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

/**
 * Integrator Login.
 *
 * @author Sultan Tezadov, Sergey Kozmin
 */
public class IntegratorLogin {
    private static final String METADATA_LOADER_PARAM_NAME = "metadata_loader";
    private static CustomDataLoader loader;
    // Logger reference.
    private static final AbstractLogger logger = Log.getLog(
            IntegratorLogin.class);

    public static LoginResult login(LoginRequestObject lro,
                                    HttpServletRequest request)
            throws RPCException {
        logger.INFO("Login started for user:" + lro.getLogin());
        long startLoginTime = System.currentTimeMillis();

        LoginResult lr = null;
        ServletContext ctx = request.getSession().getServletContext();
        try {
            LogonSession session = WebLoginManager.setLogonSession(request, lro);
            CustomDataLoader customParametersLoader
                    = getCustomParametersLoader();

            loadServerParameters(customParametersLoader, session, ctx);
            MetaData metaData = ApplicationMetadataHelper.getMetaData(session,
                    lro.getClientNow(), ctx);
            loadClientParameters(metaData, customParametersLoader, session,
                    ctx);
            lr = new LoginResult(metaData);

            UserLog.login(session);
        } catch (BadNameOrPasswordException e) {
            IntegratorHelper.throwException(e, SystemHelper.DEFAULT_LANGUAGE,
                    ctx);
        } catch (Exception e) {
            GWTHelper.throwSerializableException(e);
        }
        long endLoginTime = System.currentTimeMillis();
        float secTime = ((endLoginTime - startLoginTime) / (float) 1000);
        logger.INFO("Login for user:" + lro.getLogin() + ", finished in: "
                + secTime + "s");
        return lr;
    }

    private static void loadServerParameters(
            CustomDataLoader customParametersLoader, LogonSession session,
            ServletContext ctx) {
        if(customParametersLoader != null) {
            customParametersLoader.loadServerCustomProperties(session, ctx);
        }
    }

    private static void loadClientParameters(MetaData metaData,
                                             CustomDataLoader customParametersLoader,
                                             LogonSession session,
                                             ServletContext ctx) {
        if(customParametersLoader != null) {
            metaData.setApplicationSpecificData(
                    customParametersLoader.loadClientCustomProperties(session,
                            ctx));
        }
    }

    private static CustomDataLoader getCustomParametersLoader() {
        synchronized(METADATA_LOADER_PARAM_NAME) {
            if(loader == null) {
                loader = createCustomParametersLoader();
            }
            return loader;
        }
    }

    /**
     * Retrieve custom parameters loader.
     *
     * @return custom parameters loader object.
     */
    private static CustomDataLoader createCustomParametersLoader() {
        CustomDataLoader loader = null;
        try {
            ClassLoader cl = WarClassLoaderHelper.getClassLoader();
            String loaderName = CustomPropertiesLoader.getProperty(
                    METADATA_LOADER_PARAM_NAME);
            Class cls = Class.forName(loaderName, true, cl);
            loader = (CustomDataLoader) cls.newInstance();
        } catch (Exception e) {
            logger.DEBUG("Couldn't instantiate application parameter loader. ",
                    e);
        }
        return loader;
    }

    public static void logout(HttpServletRequest request) {
        LogonSession session = WebLoginManager.getLogonSession(request);
        UserLog.logout(session);
        WebLoginManager.cleanHttpSession(request);
    }
}