/*
 * Copyright 2009-2013 the Fess Project and the Others.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * 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 jp.sf.fess.helper.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;

import jp.sf.fess.Constants;
import jp.sf.fess.crypto.FessCipher;
import jp.sf.fess.entity.LoginInfo;
import jp.sf.fess.helper.RoleQueryHelper;
import jp.sf.fess.helper.SystemHelper;

import org.seasar.framework.util.StringUtil;
import org.seasar.struts.util.RequestUtil;

/**
 * This class returns a list of a role from a request parameter,
 * a request header and a cookie. The format of the default value
 * is "[\d]+\nrole1,role2,role3", which you can encrypt.
 * 
 * @author shinsuke
 *
 */
public class RoleQueryHelperImpl implements RoleQueryHelper, Serializable {

    private static final long serialVersionUID = 1L;

    public FessCipher fessCipher;

    public String valueSeparator = "\n";

    public String roleSeparator = ",";

    public String parameterKey;

    public boolean encryptedParameterValue = true;

    public String headerKey;

    public boolean encryptedHeaderValue = true;

    public String cookieKey;

    public boolean encryptedCookieValue = true;

    public List<String> defaultRoleList;

    public SystemHelper systemHelper;

    /* (non-Javadoc)
     * @see jp.sf.fess.helper.impl.RoleQueryHelper#build()
     */
    @Override
    public List<String> build() {
        final List<String> roleList = new ArrayList<String>();

        // request parameter
        if (StringUtil.isNotBlank(parameterKey)) {
            roleList.addAll(buildByParameter());
        }

        // request header
        if (StringUtil.isNotBlank(headerKey)) {
            roleList.addAll(buildByHeader());
        }

        // cookie
        if (StringUtil.isNotBlank(cookieKey)) {
            roleList.addAll(buildByCookie());
        }

        // JAAS roles
        final HttpSession session = RequestUtil.getRequest().getSession(false);
        if (session != null) {
            final LoginInfo loginInfo = (LoginInfo) session
                    .getAttribute(Constants.LOGIN_INFO);
            if (loginInfo != null) {
                roleList.addAll(loginInfo.getRoleList());
            }
        }

        if (defaultRoleList != null) {
            roleList.addAll(defaultRoleList);
        }

        return roleList;
    }

    protected List<String> buildByParameter() {
        final String parameter = RequestUtil.getRequest().getParameter(
                parameterKey);
        if (StringUtil.isNotEmpty(parameter)) {
            return decodedRoleList(parameter, encryptedParameterValue);
        } else {
            return Collections.emptyList();
        }
    }

    protected List<String> buildByHeader() {
        final String parameter = RequestUtil.getRequest().getHeader(headerKey);
        if (StringUtil.isNotEmpty(parameter)) {
            return decodedRoleList(parameter, encryptedHeaderValue);
        } else {
            return Collections.emptyList();
        }
    }

    protected List<String> buildByCookie() {
        final Cookie[] cookies = RequestUtil.getRequest().getCookies();
        for (final Cookie cookie : cookies) {
            if (cookieKey.equals(cookie.getName())) {
                final String value = cookie.getValue();
                if (StringUtil.isNotEmpty(value)) {
                    return decodedRoleList(value, encryptedCookieValue);
                }
            }
        }
        return Collections.emptyList();
    }

    protected List<String> decodedRoleList(String value, final boolean encrypted) {
        if (encrypted && fessCipher != null) {
            value = fessCipher.decryptoText(value);
        }

        final List<String> roleList = new ArrayList<String>();
        final String[] values = value.split(valueSeparator);
        if (values.length > 1) {
            final String[] roles = values[1].split(roleSeparator);
            for (final String role : roles) {
                roleList.add(role);
            }
        }
        return roleList;
    }

}
