package jp.co.y_net.amm.page;

import jp.co.y_net.amm.AppSession;
import jp.co.y_net.amm.AppSession.LoginUser;
import jp.co.y_net.amm.common.AppLogger;
import jp.co.y_net.amm.common.AppUtils;
import jp.co.y_net.amm.common.ResourceReader;
import jp.co.y_net.amm.dao.AppDef;
import jp.co.y_net.amm.dao.Usr;
import jp.co.y_net.amm.service.Logincheck;
import jp.co.y_net.amm.service.Logincheck.LogincheckResult;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.HiddenField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.Url.StringMode;
import org.apache.wicket.request.flow.RedirectToUrlException;
import org.apache.wicket.request.mapper.parameter.PageParameters;

public class LoginPage extends CommonFrameA {
    
    public LoginPage() {
        this(new PageParameters());
    }
    public LoginPage(PageParameters params) {
        
        /* トップへ戻る */
        add(new ExternalLink("lnkTop", ResourceReader.getStringQuick("url.back.top")));
        
        /* フィードバックパネルの設置 */
        createFeedbackPanel();
        
        final Model<String> modelChallengestringA = Model.of(challengestring.execute());
        final HiddenField<String> textChallenge = new HiddenField<String>("textChallenge", modelChallengestringA);
        final TextField<String> textLoginId = new TextField<String>("textLoginId", Model.of(""));
        final HiddenField<String> textChallengeResponse = new HiddenField<String>("textChallengeResponse", Model.of(""));
        
        Button btnLogin = new Button("btnLogin");
        btnLogin.add(new AttributeModifier("onclick", "return eventLogin(true)"));
        
        Form<Void> form =new Form<Void>("form") {
            @Override
            public void onSubmit() {
                /* ログイン処理 */
                String challengestringA = modelChallengestringA.getObject();
                String loginidB = textLoginId.getValue();
                String cresE = textChallengeResponse.getValue();
                
                /* ------------------------ */
                
                LogincheckResult logincheckResult = logincheck.executeFromAmm(loginidB, cresE, challengestringA);
                
                if(0 == logincheckResult.errorCode) {
                    /* 認証成功 */
                    
                    /*
                     * すでに別のユーザでセッションが作成されているときの処理
                     */
                    if(existOtherSession(loginidB)) {
                        error("別のユーザでログイン中です。一度ログアウトしてください。");
                        return;
                    }
                    
                    /* セッション開始 */
                    startSession(loginidB);
                    
                    /* 画面遷移 */
                    if(AppSession.get().returnPageClass != null) {
                        /* 呼び出し元が設定されている場合 */
                        setResponsePage(AppSession.get().returnPageClass, AppSession.get().returnPageParameters);
                        
                    } else {
                        
                        /* 呼び出し元が設定されていない場合 */
                        if(isMember()) {
                            throw new RedirectToUrlException(ResourceReader.getStringQuick("url.back.member"));
                        }
                        if(isOrgAdmin()) {
                            throw new RedirectToUrlException(ResourceReader.getStringQuick("url.back.orgadmin"));
                        }
                        if(isSystemAdmin()) {
                            throw new RedirectToUrlException(ResourceReader.getStringQuick("url.back.sysadmin"));
                        }
                    }
                    
                } else {
                    
                    error(Logincheck.errorMessage.get(logincheckResult.errorCode));
                }
            }
        };
        add(form);
        form.add(textChallenge);
        form.add(textLoginId);
        form.add(textChallengeResponse);
        form.add(btnLogin);
        
        
        /* 
         * パラメータにログインIDが含まれている場合の処理
         */
        String paramLoginid = params.get("loginid").toString();
        if (StringUtils.isEmpty(paramLoginid) == false) {
            
            /* 2015/10/02 引数にチャレンジレスポンスを追加 */
            Usr user = usrDao.getByLoginid(paramLoginid);
            String paramCres = params.get("cres").toString();
            if (checkParam(user, paramCres)) {
//            if (user != null && StringUtils.isEmpty(user.getCres()) == false) {
//                if(user.getCresdate() > AppUtils.createNowLong())  {
                    
                    /* チャレンジレスポンスの有効期限以内のときはログイン認証を割愛してログインする */
                    paramLoginid = AppUtils.urlDecode(paramLoginid); // URLデコード
                    
                    /* 
                     * チャレンジレスポンスの破棄
                     * 　次のケースで無限ループとなるため。
                     * 1. 権限管理されたページに権限の不足しているユーザがアクセス
                     * 2. Loginへ自動転送され、チャレンジレスポンスが有効なため、自動ログイン（「1.」へ戻る）
                     */
                    user.setCres(null);
                    user.setCresdate(-1L);
                    usrDao.update(user, AppDef.USERID_NONE); // 【更新処理】
                    
                    /*
                     * すでに別のユーザでセッションが作成されているときの処理
                     */
                    if(existOtherSession(paramLoginid)) {
                        error("別のユーザでログイン中です。一度ログアウトしてください。");
                        return;
                    }
                    
                    /* セッション開始 */
                    startSession(paramLoginid);
                    
                    /* 画面遷移 */
                    if(AppSession.get().returnPageClass != null) {
                        /* 呼び出し元が設定されている場合 */
                        throw new RestartResponseException(
                                AppSession.get().returnPageClass, AppSession.get().returnPageParameters);
                    } else {
                        /* 呼び出し元が設定されていない場合 */
                    }
//                }
            }
        }
    }
    
    /**
     * 識別パラメータの検証
     * ユーザ識別パラメータとは、
     * 　ログイン後にアクセスできる画面を呼び出すときに必要なパラメータ。
     * 　[UTF-8でURLエンコーディングされたログインID]と、
     * 　ログイン認証時に使用した[チャレンジレスポンスの値]を使用する。
     * 　例： ?loginid=user%40example.com&cres=374491d2deadaf228cd82b985d27e6af97d0518c2c1691be336a73035ad5eb9e
     *  
     * @param user 
     * @param paramCres 
     * @return
     */
    private boolean checkParam(Usr user, String paramCres) {
        if(user == null) return false;
        if(StringUtils.isEmpty(user.getCres())) return false;
        if(StringUtils.isEmpty(paramCres)) return false;
        
        if(user.getCresdate() > AppUtils.createNowLong())  {
            /* 有効期限内 */
            if(paramCres.equals(user.getCres())) {
                return true; // チャレンジレスポンスが一致する
            } else {
                AppLogger.info("ユーザ識別パラメータが指定されましたが、チャレンジレスポンスの値が一致しませんでした。");
                return false;
            }
        } else {
            /* 有効期限を過ぎている */
            return false;
        }
    }
    /**
     * ログイン認証後の処理
     * @param loginid 
     */
    private void  startSession(String loginid) {
        
        /* セッションへ登録 */
        Usr usr = usrDao.getByLoginid(loginid);
        AppSession.get().setLoginUser(usr);
        
        /* jsessionidの変更（セッション固定化攻撃対策）*/
        AppSession.get().replaceSession();

    } 
    /**
     * すでに別のユーザでセッションが作成されているときの処理
     * @param loginid
     * @return
     */
    private boolean existOtherSession(String loginid) {
        boolean existOtherSession;
        if(AppSession.get().isLogin()) {
            LoginUser loginUser = AppSession.get().getLoginUser();
            if(loginUser.getLoginid().equals(loginid) == false) {
                existOtherSession = true;
            } else {
                existOtherSession = false;
            }
        } else {
            existOtherSession = false;
        }
        return existOtherSession;
    }
    
    /**
     * コンストラクタ呼び出しが行われなくても処理対象となるメソッド
     * 戻るボタンによる遷移でも呼び出される。
     * @see org.apache.wicket.Component#onConfigure()
     */
    @Override
    protected void onConfigure() {
        /*
         * URLの調整を行う。
         * 　HTTPSでの接続が必要な時に、HTTPとして呼び出された場合には、URLを変更する。
         */
        if (ResourceReader.getBooleanQuick("use.ssl")) {
            Url url = getRequestCycle().getRequest().getOriginalUrl();
            if("https".equalsIgnoreCase(url.getProtocol()) == false) {
                url.setProtocol("https");
                throw new RedirectToUrlException(url.toString(StringMode.FULL));
            }
        }
    }



}
